Compare commits

...

41 Commits

Author SHA1 Message Date
arvinxx 805783d65b update tool error 2026-02-01 18:01:54 +08:00
arvinxx 9fdebe3eac improve tasks 2026-02-01 13:41:41 +08:00
lobehubbot da87df9533 📝 docs(bot): Auto sync agents & plugin to readme 2026-02-01 04:32:26 +00:00
semantic-release-bot 710d92d9f6 🔖 chore(release): v2.1.6 [skip ci]
### [Version 2.1.6](https://github.com/lobehub/lobe-chat/compare/v2.1.5...v2.1.6)
<sup>Released on **2026-02-01**</sup>

#### 💄 Styles

- **misc**: Improve local-system tool implement.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### Styles

* **misc**: Improve local-system tool implement, closes [#12022](https://github.com/lobehub/lobe-chat/issues/12022) ([5e203b8](https://github.com/lobehub/lobe-chat/commit/5e203b8))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2026-02-01 04:31:04 +00:00
Arvin Xu 5e203b868c 💄 style: improve local-system tool implement (#12022)
* improve local system ability

* fix build

* improve tools title render

* fix tools

* update

* try to fix lint

* update

* refactor the LocalFileCtr.ts result

* refactor the exector result
2026-02-01 12:13:27 +08:00
lobehubbot 6e4ad89c82 📝 docs(bot): Auto sync agents & plugin to readme 2026-01-31 17:01:11 +00:00
semantic-release-bot 73daa2513f 🔖 chore(release): v2.1.5 [skip ci]
### [Version&nbsp;2.1.5](https://github.com/lobehub/lobe-chat/compare/v2.1.4...v2.1.5)
<sup>Released on **2026-01-31**</sup>

#### 🐛 Bug Fixes

- **misc**: Slove the group member agents cant set skills problem.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's fixed

* **misc**: Slove the group member agents cant set skills problem, closes [#12021](https://github.com/lobehub/lobe-chat/issues/12021) ([2302940](https://github.com/lobehub/lobe-chat/commit/2302940))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2026-01-31 16:59:50 +00:00
Shinji-Li 2302940079 🐛 fix: slove the group member agents cant set skills problem (#12021)
fix: slove the group member agents cant set skills problem
2026-02-01 00:42:21 +08:00
lobehubbot 9c653e0053 📝 docs(bot): Auto sync agents & plugin to readme 2026-01-31 15:02:40 +00:00
semantic-release-bot 53c9cda9e8 🔖 chore(release): v2.1.4 [skip ci]
### [Version&nbsp;2.1.4](https://github.com/lobehub/lobe-chat/compare/v2.1.3...v2.1.4)
<sup>Released on **2026-01-31**</sup>

#### 🐛 Bug Fixes

- **stream**: Update event handling to use 'text' instead of 'content_part' in gemini 2.5 models.

#### 💄 Styles

- **misc**: Update i18n, Update Kimi K2.5 & Qwen3 Max Thinking models.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's fixed

* **stream**: Update event handling to use 'text' instead of 'content_part' in gemini 2.5 models, closes [#11235](https://github.com/lobehub/lobe-chat/issues/11235) ([a76a630](https://github.com/lobehub/lobe-chat/commit/a76a630))

#### Styles

* **misc**: Update i18n, closes [#11920](https://github.com/lobehub/lobe-chat/issues/11920) ([1a590a0](https://github.com/lobehub/lobe-chat/commit/1a590a0))
* **misc**: Update Kimi K2.5 & Qwen3 Max Thinking models, closes [#11925](https://github.com/lobehub/lobe-chat/issues/11925) ([6f9e010](https://github.com/lobehub/lobe-chat/commit/6f9e010))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2026-01-31 15:00:54 +00:00
sxjeru 6f9e01047b 💄 style: Update Kimi K2.5 & Qwen3 Max Thinking models (#11925)
* 🔨 feat(models): add new AI models and update pricing strategies

* 🐛 fix(models): remove deprecated Gemini 2.0 Flash Exp model from googleChatModels

* 🔨 fix(moonshot): update Kimi K2.5 model parameters and enhance payload handling

*  feat: 添加新的聊天模型 Kimi-K2.5 和 PaddleOCR-VL 1.5 到 siliconcloud

* Update packages/model-bank/src/aiModels/qwen.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

*  feat: 添加 Kimi K2.5 模型,更新 Qwen 模型的思维预算处理

*  feat: 添加 forceImageBase64 选项以支持强制将图像 URL 转换为 Base64

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-31 22:43:28 +08:00
sxjeru a76a630f28 🐛 fix(stream): update event handling to use 'text' instead of 'content_part' in gemini 2.5 models (#11235)
🐛 fix(stream): update event handling to use 'text' instead of 'content_part' in Google AI stream
2026-01-31 22:43:18 +08:00
Arvin Xu 338df4baf9 📝 docs: Update src directory structure to be more comprehensive (#12016)
* update e2e test

* 📝 docs: Update src directory structure to be more comprehensive

- Add missing directories: business, const, envs, helpers, tools
- Add missing root files: auth.ts, instrumentation.ts, instrumentation.node.ts, proxy.ts
- Update descriptions to be more accurate
- Sync changes across English and Chinese documentation

Fixes #9521
2026-01-31 22:42:30 +08:00
LobeHub Bot 1a590a065c 🤖 style: update i18n (#11920)
💄 style: update i18n

Co-authored-by: canisminor1990 <17870709+canisminor1990@users.noreply.github.com>
2026-01-31 20:34:06 +08:00
Arvin Xu 4a87b31246 📝 docs: improve docs (#12013)
Update docs
2026-01-31 19:46:44 +08:00
lobehubbot 83842b45b3 📝 docs(bot): Auto sync agents & plugin to readme 2026-01-31 10:44:46 +00:00
semantic-release-bot 87e3dad58a 🔖 chore(release): v2.1.3 [skip ci]
### [Version&nbsp;2.1.3](https://github.com/lobehub/lobe-chat/compare/v2.1.2...v2.1.3)
<sup>Released on **2026-01-31**</sup>

#### 🐛 Bug Fixes

- **auth**: Add AUTH_DISABLE_EMAIL_PASSWORD env to enable SSO-only mode.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's fixed

* **auth**: Add AUTH_DISABLE_EMAIL_PASSWORD env to enable SSO-only mode, closes [#12009](https://github.com/lobehub/lobe-chat/issues/12009) ([f3210a3](https://github.com/lobehub/lobe-chat/commit/f3210a3))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2026-01-31 10:43:14 +00:00
YuTengjing f3210a3f57 🐛 fix(auth): add AUTH_DISABLE_EMAIL_PASSWORD env to enable SSO-only mode (#12009) 2026-01-31 18:25:22 +08:00
Innei 8b8159eb01 🔧 chore: upgrade macOS ARM64 runner from macos-14 to macos-15 (#12006) 2026-01-31 13:12:12 +08:00
LobeHub Bot 5086a126a7 🌐 chore: translate non-English comments to English in src/store (#12001)
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-31 11:02:23 +08:00
lobehubbot a82a4bda34 📝 docs(bot): Auto sync agents & plugin to readme 2026-01-30 17:09:25 +00:00
semantic-release-bot 71b2ecd94b 🔖 chore(release): v2.1.2 [skip ci]
### [Version&nbsp;2.1.2](https://github.com/lobehub/lobe-chat/compare/v2.1.1...v2.1.2)
<sup>Released on **2026-01-30**</sup>

#### 🐛 Bug Fixes

- **misc**: Fix feishu sso provider.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's fixed

* **misc**: Fix feishu sso provider, closes [#11970](https://github.com/lobehub/lobe-chat/issues/11970) ([ffd9fff](https://github.com/lobehub/lobe-chat/commit/ffd9fff))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2026-01-30 17:07:53 +00:00
Arvin Xu ffd9fff091 🐛 fix: fix feishu sso provider (#11970) 2026-01-31 00:50:11 +08:00
LobeHub Bot 67c4bafd3f 🌐 chore: translate non-English comments to English in desktop controllers (#11978) 2026-01-31 00:49:38 +08:00
Arvin Xu 7496511917 📝 docs: improve self-hosting documents (#11994)
* update document

* update documents

* update auth

* move

* update database

* move auth

* move auth

* update
2026-01-30 20:50:05 +08:00
lobehubbot 15e89f2eee 📝 docs(bot): Auto sync agents & plugin to readme 2026-01-30 10:39:04 +00:00
semantic-release-bot 1421e991d8 🔖 chore(release): v2.1.1 [skip ci]
### [Version&nbsp;2.1.1](https://github.com/lobehub/lobe-chat/compare/v2.1.0...v2.1.1)
<sup>Released on **2026-01-30**</sup>

#### 🐛 Bug Fixes

- **misc**: Correct desktop download URL path.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's fixed

* **misc**: Correct desktop download URL path, closes [#11990](https://github.com/lobehub/lobe-chat/issues/11990) ([e46df98](https://github.com/lobehub/lobe-chat/commit/e46df98))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2026-01-30 10:37:18 +00:00
Arvin Xu f17acd7f7e ♻️ chore(docker-compose): refactor docker compose (#11989)
* improve message content

* ♻️ refactor(docker-compose): 创建精简版 deploy 配置

- 新建 docker-compose/deploy 目录,包含最小化部署配置
- 仅保留核心服务:postgresql、redis、rustfs、searxng、lobe
- 移除 Casdoor 认证服务相关配置
- 移除可观测性服务(Grafana/Prometheus/Tempo/otel-collector)
- 使用 paradedb/paradedb:latest 镜像(支持 pgvector + pg_search)
- 更新 setup.sh 指向新的 deploy 目录
- 清理 .env 示例文件中的 Casdoor 相关配置

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* update document

* update content

* update content

* improve env

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 18:15:43 +08:00
Innei e46df98907 🐛 fix: correct desktop download URL path (#11990)
Fixed the download URL path from '/download' to '/downloads' to match the actual official site path.
2026-01-30 17:53:09 +08:00
lobehubbot 2c791d749d 📝 docs(bot): Auto sync agents & plugin to readme 2026-01-30 05:57:38 +00:00
semantic-release-bot 4e982cf89f 🔖 chore(release): v2.1.0 [skip ci]
## [Version&nbsp;2.1.0](https://github.com/lobehub/lobe-chat/compare/v2.0.13...v2.1.0)
<sup>Released on **2026-01-30**</sup>

####  Features

- **misc**: Refactor cron job UI and use runtime enableBusinessFeatures flag.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's improved

* **misc**: Refactor cron job UI and use runtime enableBusinessFeatures flag, closes [#11975](https://github.com/lobehub/lobe-chat/issues/11975) ([104a19a](https://github.com/lobehub/lobe-chat/commit/104a19a))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2026-01-30 05:56:16 +00:00
Innei 104a19a8a4 feat: refactor cron job UI and use runtime enableBusinessFeatures flag (#11975)
- Replace compile-time ENABLE_BUSINESS_FEATURES constant with runtime
  serverConfigSelectors.enableBusinessFeatures for cron module
- Redesign CronJobScheduleConfig with FormGroup pattern matching Settings UI
- Update CronJobHeader with simplified layout (28px title, Switch only)
- Convert all cron feature components to use createStaticStyles with cssVar
- Add i18n keys for cron job form labels

LOBE-4540
2026-01-30 13:38:34 +08:00
lobehubbot c5a1791e32 📝 docs(bot): Auto sync agents & plugin to readme 2026-01-29 17:23:20 +00:00
semantic-release-bot 9a1a81680f 🔖 chore(release): v2.0.13 [skip ci]
### [Version&nbsp;2.0.13](https://github.com/lobehub/lobe-chat/compare/v2.0.12...v2.0.13)
<sup>Released on **2026-01-29**</sup>

#### 💄 Styles

- **misc**: Fix usage table display issues.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### Styles

* **misc**: Fix usage table display issues, closes [#10108](https://github.com/lobehub/lobe-chat/issues/10108) ([4bd82c3](https://github.com/lobehub/lobe-chat/commit/4bd82c3))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2026-01-29 17:21:49 +00:00
Rylan Cai 4bd82c397a 💄 style: fix usage table display issues (#10108)
* wip: use stack bar chart

* 💄 style: update labels

* 🐛 fix: should not include INF vales

* ♻️ refactor: improve codes

* 💄 style: improve label format

* 💄 style: improve label format
2026-01-30 01:05:02 +08:00
lobehubbot 891837b792 📝 docs(bot): Auto sync agents & plugin to readme 2026-01-29 17:01:44 +00:00
semantic-release-bot a4c1d4b687 🔖 chore(release): v2.0.12 [skip ci]
### [Version&nbsp;2.0.12](https://github.com/lobehub/lobe-chat/compare/v2.0.11...v2.0.12)
<sup>Released on **2026-01-29**</sup>

#### 🐛 Bug Fixes

- **misc**: Group publish to market should set local group market identifer.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's fixed

* **misc**: Group publish to market should set local group market identifer, closes [#11965](https://github.com/lobehub/lobe-chat/issues/11965) ([0bda4d9](https://github.com/lobehub/lobe-chat/commit/0bda4d9))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2026-01-29 17:00:18 +00:00
Shinji-Li 0bda4d9845 🐛 fix: group publish to market should set local group market identifer (#11965)
* fix: when use group in market the supervisor plugins lost

* fix: slove the group pubilsh but not set the market id into group
2026-01-29 22:30:14 +08:00
lobehubbot 7abc5142e0 📝 docs(bot): Auto sync agents & plugin to readme 2026-01-29 14:03:28 +00:00
semantic-release-bot 1b9caa92a5 🔖 chore(release): v2.0.11 [skip ci]
### [Version&nbsp;2.0.11](https://github.com/lobehub/lobe-chat/compare/v2.0.10...v2.0.11)
<sup>Released on **2026-01-29**</sup>

#### 💄 Styles

- **misc**: Fix group task render.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### Styles

* **misc**: Fix group task render, closes [#11952](https://github.com/lobehub/lobe-chat/issues/11952) ([b8ef02e](https://github.com/lobehub/lobe-chat/commit/b8ef02e))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
2026-01-29 14:02:07 +00:00
Arvin Xu b8ef02e647 💄 style: fix group task render (#11952)
* improve task messages render

* improve task messages render

* refactor agent task

* fix tests

* improved ui now

* fix

* fix supervisor issue

* add more tests

* fix agent tasks issue

* update i18n

* update createdAt

* fix tests and update dockerfile

* fix max length

* fix max length
2026-01-29 21:44:32 +08:00
454 changed files with 11729 additions and 5056 deletions
+4 -6
View File
@@ -1,6 +1,3 @@
# add a access code to lock your lobe-chat application, you can set a long password to avoid leaking. If this value contains a comma, it is a password array.
# ACCESS_CODE=lobe66
# Specify your API Key selection method, currently supporting `random` and `turn`.
# API_KEY_SELECT_MODE=random
@@ -265,9 +262,6 @@ OPENAI_API_KEY=sk-xxxxxxxxx
# Bucket request endpoint
# S3_ENDPOINT=https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxx.r2.cloudflarestorage.com
# Public access domain for the bucket
# S3_PUBLIC_DOMAIN=https://s3-for-lobechat.your-domain.com
# Bucket region, such as us-west-1, generally not needed to add
# but some service providers may require configuration
# S3_REGION=us-west-1
@@ -295,6 +289,10 @@ OPENAI_API_KEY=sk-xxxxxxxxx
# Leave empty to allow all emails
# AUTH_ALLOWED_EMAILS=example.com,admin@other.com
# Disable email/password authentication (SSO-only mode)
# Set to '1' to disable email/password sign-in and registration, only allowing SSO login
# AUTH_DISABLE_EMAIL_PASSWORD=0
# Google OAuth Configuration (for Better-Auth)
# Get credentials from: https://console.cloud.google.com/apis/credentials
# Authorized redirect URIs:
-3
View File
@@ -85,9 +85,6 @@ S3_ENDPOINT=http://localhost:${MINIO_PORT}
# S3 bucket name for storing files
S3_BUCKET=${MINIO_LOBE_BUCKET}
# Public domain for S3 file access
S3_PUBLIC_DOMAIN=http://localhost:${MINIO_PORT}
# Enable path-style S3 requests (required for MinIO)
S3_ENABLE_PATH_STYLE=1
+1 -1
View File
@@ -148,7 +148,7 @@ jobs:
# 使用 GitHub Hosted Runner
if [[ "${{ github.event_name }}" != "workflow_dispatch" ]] || [[ "${{ inputs.build_mac }}" == "true" ]]; then
echo "Using GitHub-Hosted Runner for macOS ARM64"
arm_entry='{"os": "macos-14", "name": "macos-arm64"}'
arm_entry='{"os": "macos-15", "name": "macos-arm64"}'
static_matrix=$(echo "$static_matrix" | jq -c --argjson entry "$arm_entry" '. + [$entry]')
fi
+259
View File
@@ -2,6 +2,265 @@
# Changelog
### [Version 2.1.6](https://github.com/lobehub/lobe-chat/compare/v2.1.5...v2.1.6)
<sup>Released on **2026-02-01**</sup>
#### 💄 Styles
- **misc**: Improve local-system tool implement.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### Styles
- **misc**: Improve local-system tool implement, closes [#12022](https://github.com/lobehub/lobe-chat/issues/12022) ([5e203b8](https://github.com/lobehub/lobe-chat/commit/5e203b8))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
### [Version 2.1.5](https://github.com/lobehub/lobe-chat/compare/v2.1.4...v2.1.5)
<sup>Released on **2026-01-31**</sup>
#### 🐛 Bug Fixes
- **misc**: Slove the group member agents cant set skills problem.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's fixed
- **misc**: Slove the group member agents cant set skills problem, closes [#12021](https://github.com/lobehub/lobe-chat/issues/12021) ([2302940](https://github.com/lobehub/lobe-chat/commit/2302940))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
### [Version 2.1.4](https://github.com/lobehub/lobe-chat/compare/v2.1.3...v2.1.4)
<sup>Released on **2026-01-31**</sup>
#### 🐛 Bug Fixes
- **stream**: Update event handling to use 'text' instead of 'content_part' in gemini 2.5 models.
#### 💄 Styles
- **misc**: Update i18n, Update Kimi K2.5 & Qwen3 Max Thinking models.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's fixed
- **stream**: Update event handling to use 'text' instead of 'content_part' in gemini 2.5 models, closes [#11235](https://github.com/lobehub/lobe-chat/issues/11235) ([a76a630](https://github.com/lobehub/lobe-chat/commit/a76a630))
#### Styles
- **misc**: Update i18n, closes [#11920](https://github.com/lobehub/lobe-chat/issues/11920) ([1a590a0](https://github.com/lobehub/lobe-chat/commit/1a590a0))
- **misc**: Update Kimi K2.5 & Qwen3 Max Thinking models, closes [#11925](https://github.com/lobehub/lobe-chat/issues/11925) ([6f9e010](https://github.com/lobehub/lobe-chat/commit/6f9e010))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
### [Version 2.1.3](https://github.com/lobehub/lobe-chat/compare/v2.1.2...v2.1.3)
<sup>Released on **2026-01-31**</sup>
#### 🐛 Bug Fixes
- **auth**: Add AUTH_DISABLE_EMAIL_PASSWORD env to enable SSO-only mode.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's fixed
- **auth**: Add AUTH_DISABLE_EMAIL_PASSWORD env to enable SSO-only mode, closes [#12009](https://github.com/lobehub/lobe-chat/issues/12009) ([f3210a3](https://github.com/lobehub/lobe-chat/commit/f3210a3))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
### [Version 2.1.2](https://github.com/lobehub/lobe-chat/compare/v2.1.1...v2.1.2)
<sup>Released on **2026-01-30**</sup>
#### 🐛 Bug Fixes
- **misc**: Fix feishu sso provider.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's fixed
- **misc**: Fix feishu sso provider, closes [#11970](https://github.com/lobehub/lobe-chat/issues/11970) ([ffd9fff](https://github.com/lobehub/lobe-chat/commit/ffd9fff))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
### [Version 2.1.1](https://github.com/lobehub/lobe-chat/compare/v2.1.0...v2.1.1)
<sup>Released on **2026-01-30**</sup>
#### 🐛 Bug Fixes
- **misc**: Correct desktop download URL path.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's fixed
- **misc**: Correct desktop download URL path, closes [#11990](https://github.com/lobehub/lobe-chat/issues/11990) ([e46df98](https://github.com/lobehub/lobe-chat/commit/e46df98))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version 2.1.0](https://github.com/lobehub/lobe-chat/compare/v2.0.13...v2.1.0)
<sup>Released on **2026-01-30**</sup>
#### ✨ Features
- **misc**: Refactor cron job UI and use runtime enableBusinessFeatures flag.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's improved
- **misc**: Refactor cron job UI and use runtime enableBusinessFeatures flag, closes [#11975](https://github.com/lobehub/lobe-chat/issues/11975) ([104a19a](https://github.com/lobehub/lobe-chat/commit/104a19a))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
### [Version 2.0.13](https://github.com/lobehub/lobe-chat/compare/v2.0.12...v2.0.13)
<sup>Released on **2026-01-29**</sup>
#### 💄 Styles
- **misc**: Fix usage table display issues.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### Styles
- **misc**: Fix usage table display issues, closes [#10108](https://github.com/lobehub/lobe-chat/issues/10108) ([4bd82c3](https://github.com/lobehub/lobe-chat/commit/4bd82c3))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
### [Version 2.0.12](https://github.com/lobehub/lobe-chat/compare/v2.0.11...v2.0.12)
<sup>Released on **2026-01-29**</sup>
#### 🐛 Bug Fixes
- **misc**: Group publish to market should set local group market identifer.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's fixed
- **misc**: Group publish to market should set local group market identifer, closes [#11965](https://github.com/lobehub/lobe-chat/issues/11965) ([0bda4d9](https://github.com/lobehub/lobe-chat/commit/0bda4d9))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
### [Version 2.0.11](https://github.com/lobehub/lobe-chat/compare/v2.0.10...v2.0.11)
<sup>Released on **2026-01-29**</sup>
#### 💄 Styles
- **misc**: Fix group task render.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### Styles
- **misc**: Fix group task render, closes [#11952](https://github.com/lobehub/lobe-chat/issues/11952) ([b8ef02e](https://github.com/lobehub/lobe-chat/commit/b8ef02e))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
### [Version 2.0.10](https://github.com/lobehub/lobe-chat/compare/v2.0.9...v2.0.10)
<sup>Released on **2026-01-29**</sup>
+50 -56
View File
@@ -8,24 +8,22 @@ ARG USE_CN_MIRROR
ENV DEBIAN_FRONTEND="noninteractive"
RUN <<'EOF'
set -e
if [ "${USE_CN_MIRROR:-false}" = "true" ]; then
sed -i "s/deb.debian.org/mirrors.ustc.edu.cn/g" "/etc/apt/sources.list.d/debian.sources"
fi
apt update
apt install ca-certificates proxychains-ng -qy
mkdir -p /distroless/bin /distroless/etc /distroless/etc/ssl/certs /distroless/lib
cp /usr/lib/$(arch)-linux-gnu/libproxychains.so.4 /distroless/lib/libproxychains.so.4
cp /usr/lib/$(arch)-linux-gnu/libdl.so.2 /distroless/lib/libdl.so.2
cp /usr/bin/proxychains4 /distroless/bin/proxychains
cp /etc/proxychains4.conf /distroless/etc/proxychains4.conf
cp /usr/lib/$(arch)-linux-gnu/libstdc++.so.6 /distroless/lib/libstdc++.so.6
cp /usr/lib/$(arch)-linux-gnu/libgcc_s.so.1 /distroless/lib/libgcc_s.so.1
cp /usr/local/bin/node /distroless/bin/node
cp /etc/ssl/certs/ca-certificates.crt /distroless/etc/ssl/certs/ca-certificates.crt
rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/*
EOF
RUN set -e && \
if [ "${USE_CN_MIRROR:-false}" = "true" ]; then \
sed -i "s/deb.debian.org/mirrors.ustc.edu.cn/g" "/etc/apt/sources.list.d/debian.sources"; \
fi && \
apt update && \
apt install ca-certificates proxychains-ng -qy && \
mkdir -p /distroless/bin /distroless/etc /distroless/etc/ssl/certs /distroless/lib && \
cp /usr/lib/$(arch)-linux-gnu/libproxychains.so.4 /distroless/lib/libproxychains.so.4 && \
cp /usr/lib/$(arch)-linux-gnu/libdl.so.2 /distroless/lib/libdl.so.2 && \
cp /usr/bin/proxychains4 /distroless/bin/proxychains && \
cp /etc/proxychains4.conf /distroless/etc/proxychains4.conf && \
cp /usr/lib/$(arch)-linux-gnu/libstdc++.so.6 /distroless/lib/libstdc++.so.6 && \
cp /usr/lib/$(arch)-linux-gnu/libgcc_s.so.1 /distroless/lib/libgcc_s.so.1 && \
cp /usr/local/bin/node /distroless/bin/node && \
cp /etc/ssl/certs/ca-certificates.crt /distroless/etc/ssl/certs/ca-certificates.crt && \
rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/*
## Builder image, install all the dependencies and build the app
FROM base AS builder
@@ -77,23 +75,21 @@ COPY patches ./patches
# bring in desktop workspace manifest so pnpm can resolve it
COPY apps/desktop/src/main/package.json ./apps/desktop/src/main/package.json
RUN <<'EOF'
set -e
if [ "${USE_CN_MIRROR:-false}" = "true" ]; then
export SENTRYCLI_CDNURL="https://npmmirror.com/mirrors/sentry-cli"
npm config set registry "https://registry.npmmirror.com/"
echo 'canvas_binary_host_mirror=https://npmmirror.com/mirrors/canvas' >> .npmrc
fi
export COREPACK_NPM_REGISTRY=$(npm config get registry | sed 's/\/$//')
npm i -g corepack@latest
corepack enable
corepack use $(sed -n 's/.*"packageManager": "\(.*\)".*/\1/p' package.json)
pnpm i
mkdir -p /deps
cd /deps
pnpm init
pnpm add pg drizzle-orm
EOF
RUN set -e && \
if [ "${USE_CN_MIRROR:-false}" = "true" ]; then \
export SENTRYCLI_CDNURL="https://npmmirror.com/mirrors/sentry-cli"; \
npm config set registry "https://registry.npmmirror.com/"; \
echo 'canvas_binary_host_mirror=https://npmmirror.com/mirrors/canvas' >> .npmrc; \
fi && \
export COREPACK_NPM_REGISTRY=$(npm config get registry | sed 's/\/$//') && \
npm i -g corepack@latest && \
corepack enable && \
corepack use $(sed -n 's/.*"packageManager": "\(.*\)".*/\1/p' package.json) && \
pnpm i && \
mkdir -p /deps && \
cd /deps && \
pnpm init && \
pnpm add pg drizzle-orm
COPY . .
@@ -101,17 +97,15 @@ COPY . .
RUN npm run build:docker
# Prepare desktop export assets for Electron packaging (if generated)
RUN <<'EOF'
set -e
if [ -d "/app/out" ]; then
mkdir -p /app/apps/desktop/dist/next
cp -a /app/out/. /app/apps/desktop/dist/next/
echo "✅ Copied Next export output into /app/apps/desktop/dist/next"
else
echo "️ No Next export output found at /app/out, creating empty directory"
mkdir -p /app/apps/desktop/dist/next
fi
EOF
RUN set -e && \
if [ -d "/app/out" ]; then \
mkdir -p /app/apps/desktop/dist/next && \
cp -a /app/out/. /app/apps/desktop/dist/next/ && \
echo "Copied Next export output into /app/apps/desktop/dist/next"; \
else \
echo "No Next export output found at /app/out, creating empty directory" && \
mkdir -p /app/apps/desktop/dist/next; \
fi
## Application image, copy all the files for production
FROM busybox:latest AS app
@@ -138,12 +132,10 @@ COPY --from=builder /deps/node_modules/drizzle-orm /app/node_modules/drizzle-orm
COPY --from=builder /app/scripts/serverLauncher/startServer.js /app/startServer.js
COPY --from=builder /app/scripts/_shared /app/scripts/_shared
RUN <<'EOF'
set -e
addgroup -S -g 1001 nodejs
adduser -D -G nodejs -H -S -h /app -u 1001 nextjs
chown -R nextjs:nodejs /app /etc/proxychains4.conf
EOF
RUN set -e && \
addgroup -S -g 1001 nodejs && \
adduser -D -G nodejs -H -S -h /app -u 1001 nextjs && \
chown -R nextjs:nodejs /app /etc/proxychains4.conf
## Production image, copy all the files and run next
FROM scratch
@@ -166,14 +158,12 @@ ENV HOSTNAME="0.0.0.0" \
PORT="3210"
# General Variables
ENV ACCESS_CODE="" \
APP_URL="" \
ENV APP_URL="" \
API_KEY_SELECT_MODE="" \
DEFAULT_AGENT_CONFIG="" \
SYSTEM_AGENT="" \
FEATURE_FLAGS="" \
PROXY_URL="" \
ENABLE_AUTH_PROTECTION=""
PROXY_URL=""
# Database
ENV KEY_VAULTS_SECRET="" \
@@ -184,6 +174,10 @@ ENV KEY_VAULTS_SECRET="" \
ENV AUTH_SECRET="" \
AUTH_SSO_PROVIDERS="" \
AUTH_ALLOWED_EMAILS="" \
AUTH_TRUSTED_ORIGINS="" \
AUTH_DISABLE_EMAIL_PASSWORD="" \
AUTH_EMAIL_VERIFICATION="" \
AUTH_ENABLE_MAGIC_LINK="" \
# Google
AUTH_GOOGLE_ID="" \
AUTH_GOOGLE_SECRET="" \
+3 -4
View File
@@ -37,7 +37,7 @@ Were building the worlds largest humanagent co-evolving network.
[![][share-mastodon-shield]][share-mastodon-link]
[![][share-linkedin-shield]][share-linkedin-link]
<sup>Agent teams that grow with you</sup>
<sup>Agent teammates that grow with you</sup>
[![][github-trending-shield]][github-trending-url]
@@ -581,7 +581,7 @@ LobeHub provides Self-Hosted Version with Vercel, Alibaba Cloud, and [Docker Ima
"If you want to deploy this service yourself on Vercel, Zeabur or Alibaba Cloud, you can follow these steps:
- Prepare your [OpenAI API Key](https://platform.openai.com/account/api-keys).
- Click the button below to start deployment: Log in directly with your GitHub account, and remember to fill in the `OPENAI_API_KEY`(required) and `ACCESS_CODE` (recommended) on the environment variable section.
- Click the button below to start deployment: Log in directly with your GitHub account, and remember to fill in the `OPENAI_API_KEY`(required) on the environment variable section.
- After deployment, you can start using it.
- Bind a custom domain (optional): The DNS of the domain assigned by Vercel is polluted in some areas; binding a custom domain can connect directly.
@@ -647,7 +647,6 @@ This project provides some additional configuration items set with environment v
| -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `OPENAI_API_KEY` | Yes | This is the API key you apply on the OpenAI account page | `sk-xxxxxx...xxxxxx` |
| `OPENAI_PROXY_URL` | No | If you manually configure the OpenAI interface proxy, you can use this configuration item to override the default OpenAI API request base URL | `https://api.chatanywhere.cn` or `https://aihubmix.com/v1` <br/>The default value is<br/>`https://api.openai.com/v1` |
| `ACCESS_CODE` | No | Add a password to access this service; you can set a long password to avoid leaking. If this value contains a comma, it is a password array. | `awCTe)re_r74` or `rtrt_ewee3@09!` or `code1,code2,code3` |
| `OPENAI_MODEL_LIST` | No | Used to control the model list. Use `+` to add a model, `-` to hide a model, and `model_name=display_name` to customize the display name of a model, separated by commas. | `qwen-7b-chat,+glm-6b,-gpt-3.5-turbo` |
> \[!NOTE]
@@ -829,7 +828,7 @@ This project is [LobeHub Community License](./LICENSE) licensed.
[codespaces-link]: https://codespaces.new/lobehub/lobe-chat
[codespaces-shield]: https://github.com/codespaces/badge.svg
[deploy-button-image]: https://vercel.com/button
[deploy-link]: https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat&env=OPENAI_API_KEY,ACCESS_CODE&envDescription=Find%20your%20OpenAI%20API%20Key%20by%20click%20the%20right%20Learn%20More%20button.%20%7C%20Access%20Code%20can%20protect%20your%20website&envLink=https%3A%2F%2Fplatform.openai.com%2Faccount%2Fapi-keys&project-name=lobe-chat&repository-name=lobe-chat
[deploy-link]: https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat&env=OPENAI_API_KEY&envDescription=Find%20your%20OpenAI%20API%20Key%20by%20click%20the%20right%20Learn%20More%20button.&envLink=https%3A%2F%2Fplatform.openai.com%2Faccount%2Fapi-keys&project-name=lobe-chat&repository-name=lobe-chat
[deploy-on-alibaba-cloud-button-image]: https://service-info-public.oss-cn-hangzhou.aliyuncs.com/computenest-en.svg
[deploy-on-alibaba-cloud-link]: https://computenest.console.aliyun.com/service/instance/create/default?type=user&ServiceName=LobeHub%E7%A4%BE%E5%8C%BA%E7%89%88
[deploy-on-repocloud-button-image]: https://d16t0pc4846x52.cloudfront.net/deploylobe.svg
+3 -4
View File
@@ -35,7 +35,7 @@ LobeHub 是一个工作与生活空间,用于发现、构建并与会随着您
[![][share-weibo-shield]][share-weibo-link]
[![][share-mastodon-shield]][share-mastodon-link]
<sup>Agent teams that grow with you</sup>
<sup>Agent teammates that grow with you</sup>
[![][github-trending-shield]][github-trending-url]
[![][github-hello-shield]][github-hello-url]
@@ -555,7 +555,7 @@ LobeHub 提供了 Vercel 的 自托管版本 和 [Docker 镜像][docker-release-
如果想在 Vercel 、 Zeabur 或 阿里云 上部署该服务,可以按照以下步骤进行操作:
- 准备好你的 [OpenAI API Key](https://platform.openai.com/account/api-keys) 。
- 点击下方按钮开始部署: 直接使用 GitHub 账号登录即可,记得在环境变量页填入 `OPENAI_API_KEY` (必填) and `ACCESS_CODE`(推荐)
- 点击下方按钮开始部署: 直接使用 GitHub 账号登录即可,记得在环境变量页填入 `OPENAI_API_KEY` (必填);
- 部署完毕后,即可开始使用;
- 绑定自定义域名(可选):Vercel 分配的域名 DNS 在某些区域被污染了,绑定自定义域名即可直连。目前 Zeabur 提供的域名还未被污染,大多数地区都可以直连。
@@ -621,7 +621,6 @@ docker compose up -d
| ------------------- | ---- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `OPENAI_API_KEY` | 必选 | 这是你在 OpenAI 账户页面申请的 API 密钥 | `sk-xxxxxx...xxxxxx` |
| `OPENAI_PROXY_URL` | 可选 | 如果你手动配置了 OpenAI 接口代理,可以使用此配置项来覆盖默认的 OpenAI API 请求基础 URL | `https://api.chatanywhere.cn``https://aihubmix.com/v1`<br/>默认值:<br/>`https://api.openai.com/v1` |
| `ACCESS_CODE` | 可选 | 添加访问此服务的密码,你可以设置一个长密码以防被爆破,该值用逗号分隔时为密码数组 | `awCTe)re_r74` or `rtrt_ewee3@09!` or `code1,code2,code3` |
| `OPENAI_MODEL_LIST` | 可选 | 用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名` 来自定义模型的展示名,用英文逗号隔开。 | `qwen-7b-chat,+glm-6b,-gpt-3.5-turbo` |
> \[!NOTE]
@@ -843,7 +842,7 @@ This project is [LobeHub Community License](./LICENSE) licensed.
[codespaces-link]: https://codespaces.new/lobehub/lobe-chat
[codespaces-shield]: https://github.com/codespaces/badge.svg
[deploy-button-image]: https://vercel.com/button
[deploy-link]: https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat&env=OPENAI_API_KEY,ACCESS_CODE&envDescription=Find%20your%20OpenAI%20API%20Key%20by%20click%20the%20right%20Learn%20More%20button.%20%7C%20Access%20Code%20can%20protect%20your%20website&envLink=https%3A%2F%2Fplatform.openai.com%2Faccount%2Fapi-keys&project-name=lobe-chat&repository-name=lobe-chat
[deploy-link]: https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat&env=OPENAI_API_KEY&envDescription=Find%20your%20OpenAI%20API%20Key%20by%20click%20the%20right%20Learn%20More%20button.&envLink=https%3A%2F%2Fplatform.openai.com%2Faccount%2Fapi-keys&project-name=lobe-chat&repository-name=lobe-chat
[deploy-on-alibaba-cloud-button-image]: https://service-info-public.oss-cn-hangzhou.aliyuncs.com/computenest-en.svg
[deploy-on-alibaba-cloud-link]: https://computenest.console.aliyun.com/service/instance/create/default?type=user&ServiceName=LobeHub%E7%A4%BE%E5%8C%BA%E7%89%88
[deploy-on-sealos-button-image]: https://raw.githubusercontent.com/labring-actions/templates/main/Deploy-on-Sealos.svg
+4 -4
View File
@@ -12,11 +12,11 @@
"main": "./dist/main/index.js",
"scripts": {
"build": "electron-vite build",
"build-local": "npm run build && electron-builder --dir --config electron-builder.mjs --c.mac.notarize=false -c.mac.identity=null --c.asar=false",
"build:linux": "npm run build && electron-builder --linux --config electron-builder.mjs --publish never",
"build:mac": "npm run build && electron-builder --mac --config electron-builder.mjs --publish never",
"build:mac:local": "npm run build && UPDATE_CHANNEL=nightly electron-builder --mac --config electron-builder.mjs --publish never",
"build:win": "npm run build && electron-builder --win --config electron-builder.mjs --publish never",
"build-local": "npm run build && electron-builder --dir --config electron-builder.mjs --c.mac.notarize=false -c.mac.identity=null --c.asar=false",
"dev": "electron-vite dev",
"dev:static": "cross-env DESKTOP_RENDERER_STATIC=1 npm run electron:dev",
"electron:dev": "electron-vite dev",
@@ -47,9 +47,6 @@
"get-port-please": "^3.2.0",
"superjson": "^2.2.6"
},
"optionalDependencies": {
"node-mac-permissions": "^2.5.0"
},
"devDependencies": {
"@electron-toolkit/eslint-config-prettier": "^3.0.0",
"@electron-toolkit/eslint-config-ts": "^3.1.0",
@@ -103,6 +100,9 @@
"vitest": "^3.2.4",
"zod": "^3.25.76"
},
"optionalDependencies": {
"node-mac-permissions": "^2.5.0"
},
"pnpm": {
"onlyBuiltDependencies": [
"@napi-rs/canvas",
@@ -218,8 +218,13 @@ export default class LocalFileCtr extends ControllerModule {
}
@IpcMethod()
async listLocalFiles({ path: dirPath }: ListLocalFileParams): Promise<FileResult[]> {
logger.debug('Listing directory contents:', { dirPath });
async listLocalFiles({
path: dirPath,
sortBy = 'modifiedTime',
sortOrder = 'desc',
limit = 100,
}: ListLocalFileParams): Promise<{ files: FileResult[]; totalCount: number }> {
logger.debug('Listing directory contents:', { dirPath, limit, sortBy, sortOrder });
const results: FileResult[] = [];
try {
@@ -256,22 +261,51 @@ export default class LocalFileCtr extends ControllerModule {
}
}
// Sort entries: folders first, then by name
// Sort entries based on sortBy and sortOrder
results.sort((a, b) => {
if (a.isDirectory !== b.isDirectory) {
return a.isDirectory ? -1 : 1; // Directories first
let comparison = 0;
switch (sortBy) {
case 'name': {
comparison = (a.name || '').localeCompare(b.name || '');
break;
}
case 'modifiedTime': {
comparison = a.modifiedTime.getTime() - b.modifiedTime.getTime();
break;
}
case 'createdTime': {
comparison = a.createdTime.getTime() - b.createdTime.getTime();
break;
}
case 'size': {
comparison = a.size - b.size;
break;
}
default: {
comparison = a.modifiedTime.getTime() - b.modifiedTime.getTime();
}
}
// Add null/undefined checks for robustness if needed, though names should exist
return (a.name || '').localeCompare(b.name || ''); // Then sort by name
return sortOrder === 'desc' ? -comparison : comparison;
});
logger.debug('Directory listing successful', { dirPath, resultCount: results.length });
return results;
const totalCount = results.length;
// Apply limit
const limitedResults = results.slice(0, limit);
logger.debug('Directory listing successful', {
dirPath,
resultCount: limitedResults.length,
totalCount,
});
return { files: limitedResults, totalCount };
} catch (error) {
logger.error(`Failed to list directory ${dirPath}:`, error);
// Rethrow or return an empty array/error object depending on desired behavior
// For now, returning empty array on error listing directory itself
return [];
// For now, returning empty result on error listing directory itself
return { files: [], totalCount: 0 };
}
}
@@ -59,14 +59,14 @@ interface McpInstallParams {
*/
export default class McpInstallController extends ControllerModule {
/**
* 处理 MCP 插件安装请求
* @param parsedData 解析后的协议数据
* @returns 是否处理成功
* Handle MCP plugin installation request
* @param parsedData Parsed protocol data
* @returns Whether processing succeeded
*/
@protocolHandler('install')
public async handleInstallRequest(parsedData: McpInstallParams): Promise<boolean> {
try {
// 从参数中提取必需字段
// Extract required fields from parameters
const { id, schema: schemaParam, marketId } = parsedData;
if (!id) {
@@ -76,11 +76,11 @@ export default class McpInstallController extends ControllerModule {
return false;
}
// 映射协议来源
// Map protocol source
const isOfficialMarket = marketId === 'lobehub';
// 对于官方市场,schema 是可选的;对于第三方市场,schema 是必需的
// For official marketplace, schema is optional; for third-party marketplace, schema is required
if (!isOfficialMarket && !schemaParam) {
logger.warn(`🔧 [McpInstall] Schema is required for third-party marketplace:`, {
marketId,
@@ -90,7 +90,7 @@ export default class McpInstallController extends ControllerModule {
let mcpSchema: McpSchema | undefined;
// 如果提供了 schema 参数,则解析和验证
// If schema parameter is provided, parse and validate
if (schemaParam) {
try {
mcpSchema = JSON.parse(schemaParam);
@@ -104,7 +104,7 @@ export default class McpInstallController extends ControllerModule {
return false;
}
// 验证 identifier 与 id 参数匹配
// Verify identifier matches id parameter
if (mcpSchema.identifier !== id) {
logger.error(`🔧 [McpInstall] Schema identifier does not match URL id parameter:`, {
schemaId: mcpSchema.identifier,
@@ -122,7 +122,7 @@ export default class McpInstallController extends ControllerModule {
pluginVersion: mcpSchema?.version || 'Unknown',
});
// 广播安装请求到前端
// Broadcast installation request to frontend
const installRequest = {
marketId,
pluginId: id,
@@ -136,7 +136,7 @@ export default class McpInstallController extends ControllerModule {
pluginName: installRequest.schema?.name || 'Unknown',
});
// 通过应用实例广播到前端
// Broadcast to frontend via app instance
if (this.app?.browserManager) {
this.app.browserManager.broadcastToWindow('app', 'mcpInstallRequest', installRequest);
logger.debug(`🔧 [McpInstall] Install request broadcasted successfully`);
@@ -88,7 +88,7 @@ export default class NetworkProxyCtr extends ControllerModule {
}
/**
* 测试代理连接
* Test proxy connection
*/
@IpcMethod()
async testProxyConnection(url: string): Promise<{ message?: string; success: boolean }> {
@@ -108,7 +108,7 @@ export default class NetworkProxyCtr extends ControllerModule {
}
/**
* 测试指定代理配置
* Test specified proxy configuration
*/
@IpcMethod()
async testProxyConfig({
@@ -131,17 +131,17 @@ export default class NetworkProxyCtr extends ControllerModule {
}
/**
* 应用初始代理设置
* Apply initial proxy settings
*/
async beforeAppReady(): Promise<void> {
try {
// 获取存储的代理设置
// Get stored proxy settings
const networkProxy = this.app.storeManager.get(
'networkProxy',
defaultProxySettings,
) as NetworkProxySettings;
// 验证配置
// Validate configuration
const validation = ProxyConfigValidator.validate(networkProxy);
if (!validation.isValid) {
logger.warn('Invalid stored proxy configuration, using defaults:', validation.errors);
@@ -158,7 +158,7 @@ export default class NetworkProxyCtr extends ControllerModule {
});
} catch (error) {
logger.error('Failed to apply initial proxy settings:', error);
// 出错时使用默认设置
// Use default settings on error
try {
await ProxyDispatcherManager.applyProxySettings(defaultProxySettings);
logger.info('Fallback to default proxy settings');
@@ -162,7 +162,7 @@ export default class RemoteServerSyncCtr extends ControllerModule {
});
});
// 5. 监听请求本身的错误(如 DNS 解析失败)
// 5. Listen for request errors (e.g., DNS resolution failure)
clientReq.on('error', (error) => {
logger.error(`${logPrefix} Error forwarding request:`, error);
if (sender.isDestroyed()) return;
@@ -196,7 +196,7 @@ export default class RemoteServerSyncCtr extends ControllerModule {
delete requestHeaders['connection']; // Often causes issues
// delete requestHeaders['content-length']; // Let node handle it based on body
// 读取代理配置
// Read proxy configuration
const proxyConfig = this.app.storeManager.get('networkProxy', defaultProxySettings);
let agent;
@@ -20,8 +20,8 @@ vi.mock('@/utils/logger', () => ({
// Mock file-loaders
vi.mock('@lobechat/file-loaders', () => ({
SYSTEM_FILES_TO_IGNORE: ['.DS_Store', 'Thumbs.db'],
loadFile: vi.fn(),
SYSTEM_FILES_TO_IGNORE: ['.DS_Store', 'Thumbs.db', '$RECYCLE.BIN'],
}));
// Mock electron
@@ -553,6 +553,514 @@ describe('LocalFileCtr', () => {
});
});
describe('listLocalFiles', () => {
it('should list directory contents successfully', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue(['file1.txt', 'file2.txt', 'folder1']);
vi.mocked(mockFsPromises.stat).mockImplementation(async (filePath) => {
const name = (filePath as string).split('/').pop();
if (name === 'folder1') {
return {
isDirectory: () => true,
birthtime: new Date('2024-01-01'),
mtime: new Date('2024-01-15'),
atime: new Date('2024-01-20'),
size: 4096,
} as any;
}
return {
isDirectory: () => false,
birthtime: new Date('2024-01-02'),
mtime: new Date('2024-01-10'),
atime: new Date('2024-01-18'),
size: 1024,
} as any;
});
const result = await localFileCtr.listLocalFiles({ path: '/test' });
expect(result.files).toHaveLength(3);
expect(result.totalCount).toBe(3);
expect(mockFsPromises.readdir).toHaveBeenCalledWith('/test');
});
it('should filter out system files like .DS_Store and Thumbs.db', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue([
'file1.txt',
'.DS_Store',
'Thumbs.db',
'folder1',
]);
vi.mocked(mockFsPromises.stat).mockImplementation(async (filePath) => {
const name = (filePath as string).split('/').pop();
if (name === 'folder1') {
return {
isDirectory: () => true,
birthtime: new Date('2024-01-01'),
mtime: new Date('2024-01-15'),
atime: new Date('2024-01-20'),
size: 4096,
} as any;
}
return {
isDirectory: () => false,
birthtime: new Date('2024-01-02'),
mtime: new Date('2024-01-10'),
atime: new Date('2024-01-18'),
size: 1024,
} as any;
});
const result = await localFileCtr.listLocalFiles({ path: '/test' });
// Should only contain file1.txt and folder1, not .DS_Store or Thumbs.db
expect(result.files).toHaveLength(2);
expect(result.totalCount).toBe(2);
expect(result.files.map((r) => r.name)).not.toContain('.DS_Store');
expect(result.files.map((r) => r.name)).not.toContain('Thumbs.db');
expect(result.files.map((r) => r.name)).toContain('folder1');
expect(result.files.map((r) => r.name)).toContain('file1.txt');
});
it('should filter out $RECYCLE.BIN system folder', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue(['file1.txt', '$RECYCLE.BIN', 'folder1']);
vi.mocked(mockFsPromises.stat).mockImplementation(async (filePath) => {
const name = (filePath as string).split('/').pop();
const isDir = name === 'folder1' || name === '$RECYCLE.BIN';
return {
isDirectory: () => isDir,
birthtime: new Date('2024-01-01'),
mtime: new Date('2024-01-15'),
atime: new Date('2024-01-20'),
size: isDir ? 4096 : 1024,
} as any;
});
const result = await localFileCtr.listLocalFiles({ path: '/test' });
// Should not contain $RECYCLE.BIN
expect(result.files).toHaveLength(2);
expect(result.totalCount).toBe(2);
expect(result.files.map((r) => r.name)).not.toContain('$RECYCLE.BIN');
});
it('should sort by name ascending when specified', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue(['zebra.txt', 'alpha.txt', 'apple.txt']);
vi.mocked(mockFsPromises.stat).mockResolvedValue({
isDirectory: () => false,
birthtime: new Date('2024-01-01'),
mtime: new Date('2024-01-15'),
atime: new Date('2024-01-20'),
size: 1024,
} as any);
const result = await localFileCtr.listLocalFiles({
path: '/test',
sortBy: 'name',
sortOrder: 'asc',
});
expect(result.files.map((r) => r.name)).toEqual(['alpha.txt', 'apple.txt', 'zebra.txt']);
});
it('should sort by modifiedTime descending by default', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue(['old.txt', 'new.txt', 'mid.txt']);
vi.mocked(mockFsPromises.stat).mockImplementation(async (filePath) => {
const name = (filePath as string).split('/').pop();
const dates: Record<string, Date> = {
'new.txt': new Date('2024-01-20'),
'mid.txt': new Date('2024-01-15'),
'old.txt': new Date('2024-01-01'),
};
return {
isDirectory: () => false,
birthtime: new Date('2024-01-01'),
mtime: dates[name!] || new Date('2024-01-01'),
atime: new Date('2024-01-20'),
size: 1024,
} as any;
});
const result = await localFileCtr.listLocalFiles({ path: '/test' });
// Default sort: modifiedTime descending (newest first)
expect(result.files.map((r) => r.name)).toEqual(['new.txt', 'mid.txt', 'old.txt']);
});
it('should sort by size ascending when specified', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue(['large.txt', 'small.txt', 'medium.txt']);
vi.mocked(mockFsPromises.stat).mockImplementation(async (filePath) => {
const name = (filePath as string).split('/').pop();
const sizes: Record<string, number> = {
'large.txt': 10000,
'medium.txt': 5000,
'small.txt': 1000,
};
return {
isDirectory: () => false,
birthtime: new Date('2024-01-01'),
mtime: new Date('2024-01-15'),
atime: new Date('2024-01-20'),
size: sizes[name!] || 1024,
} as any;
});
const result = await localFileCtr.listLocalFiles({
path: '/test',
sortBy: 'size',
sortOrder: 'asc',
});
expect(result.files.map((r) => r.name)).toEqual(['small.txt', 'medium.txt', 'large.txt']);
});
it('should apply limit parameter', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue([
'file1.txt',
'file2.txt',
'file3.txt',
'file4.txt',
'file5.txt',
]);
vi.mocked(mockFsPromises.stat).mockResolvedValue({
isDirectory: () => false,
birthtime: new Date('2024-01-01'),
mtime: new Date('2024-01-15'),
atime: new Date('2024-01-20'),
size: 1024,
} as any);
const result = await localFileCtr.listLocalFiles({
path: '/test',
limit: 3,
});
expect(result.files).toHaveLength(3);
expect(result.totalCount).toBe(5); // Total is 5, but limited to 3
});
it('should use default limit of 100', async () => {
// Create 150 files
const files = Array.from({ length: 150 }, (_, i) => `file${i}.txt`);
vi.mocked(mockFsPromises.readdir).mockResolvedValue(files);
vi.mocked(mockFsPromises.stat).mockResolvedValue({
isDirectory: () => false,
birthtime: new Date('2024-01-01'),
mtime: new Date('2024-01-15'),
atime: new Date('2024-01-20'),
size: 1024,
} as any);
const result = await localFileCtr.listLocalFiles({ path: '/test' });
expect(result.files).toHaveLength(100);
expect(result.totalCount).toBe(150); // Total is 150, but limited to 100
});
it('should sort by createdTime ascending when specified', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue([
'newest.txt',
'oldest.txt',
'middle.txt',
]);
vi.mocked(mockFsPromises.stat).mockImplementation(async (filePath) => {
const name = (filePath as string).split('/').pop();
const dates: Record<string, Date> = {
'newest.txt': new Date('2024-03-01'),
'middle.txt': new Date('2024-02-01'),
'oldest.txt': new Date('2024-01-01'),
};
return {
isDirectory: () => false,
birthtime: dates[name!] || new Date('2024-01-01'),
mtime: new Date('2024-01-15'),
atime: new Date('2024-01-20'),
size: 1024,
} as any;
});
const result = await localFileCtr.listLocalFiles({
path: '/test',
sortBy: 'createdTime',
sortOrder: 'asc',
});
expect(result.files.map((r) => r.name)).toEqual(['oldest.txt', 'middle.txt', 'newest.txt']);
});
it('should sort by createdTime descending when specified', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue([
'newest.txt',
'oldest.txt',
'middle.txt',
]);
vi.mocked(mockFsPromises.stat).mockImplementation(async (filePath) => {
const name = (filePath as string).split('/').pop();
const dates: Record<string, Date> = {
'newest.txt': new Date('2024-03-01'),
'middle.txt': new Date('2024-02-01'),
'oldest.txt': new Date('2024-01-01'),
};
return {
isDirectory: () => false,
birthtime: dates[name!] || new Date('2024-01-01'),
mtime: new Date('2024-01-15'),
atime: new Date('2024-01-20'),
size: 1024,
} as any;
});
const result = await localFileCtr.listLocalFiles({
path: '/test',
sortBy: 'createdTime',
sortOrder: 'desc',
});
expect(result.files.map((r) => r.name)).toEqual(['newest.txt', 'middle.txt', 'oldest.txt']);
});
it('should sort by name descending when specified', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue(['alpha.txt', 'zebra.txt', 'middle.txt']);
vi.mocked(mockFsPromises.stat).mockResolvedValue({
isDirectory: () => false,
birthtime: new Date('2024-01-01'),
mtime: new Date('2024-01-15'),
atime: new Date('2024-01-20'),
size: 1024,
} as any);
const result = await localFileCtr.listLocalFiles({
path: '/test',
sortBy: 'name',
sortOrder: 'desc',
});
expect(result.files.map((r) => r.name)).toEqual(['zebra.txt', 'middle.txt', 'alpha.txt']);
});
it('should sort by size descending when specified', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue(['small.txt', 'large.txt', 'medium.txt']);
vi.mocked(mockFsPromises.stat).mockImplementation(async (filePath) => {
const name = (filePath as string).split('/').pop();
const sizes: Record<string, number> = {
'large.txt': 10000,
'medium.txt': 5000,
'small.txt': 1000,
};
return {
isDirectory: () => false,
birthtime: new Date('2024-01-01'),
mtime: new Date('2024-01-15'),
atime: new Date('2024-01-20'),
size: sizes[name!] || 1024,
} as any;
});
const result = await localFileCtr.listLocalFiles({
path: '/test',
sortBy: 'size',
sortOrder: 'desc',
});
expect(result.files.map((r) => r.name)).toEqual(['large.txt', 'medium.txt', 'small.txt']);
});
it('should sort by modifiedTime ascending when specified', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue(['old.txt', 'new.txt', 'mid.txt']);
vi.mocked(mockFsPromises.stat).mockImplementation(async (filePath) => {
const name = (filePath as string).split('/').pop();
const dates: Record<string, Date> = {
'new.txt': new Date('2024-01-20'),
'mid.txt': new Date('2024-01-15'),
'old.txt': new Date('2024-01-01'),
};
return {
isDirectory: () => false,
birthtime: new Date('2024-01-01'),
mtime: dates[name!] || new Date('2024-01-01'),
atime: new Date('2024-01-20'),
size: 1024,
} as any;
});
const result = await localFileCtr.listLocalFiles({
path: '/test',
sortBy: 'modifiedTime',
sortOrder: 'asc',
});
expect(result.files.map((r) => r.name)).toEqual(['old.txt', 'mid.txt', 'new.txt']);
});
it('should handle empty directory with sort options', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue([]);
const result = await localFileCtr.listLocalFiles({
path: '/empty',
sortBy: 'name',
sortOrder: 'asc',
});
expect(result.files).toEqual([]);
expect(result.totalCount).toBe(0);
});
it('should apply limit after sorting', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue([
'file1.txt',
'file2.txt',
'file3.txt',
'file4.txt',
'file5.txt',
]);
vi.mocked(mockFsPromises.stat).mockImplementation(async (filePath) => {
const name = (filePath as string).split('/').pop();
const dates: Record<string, Date> = {
'file1.txt': new Date('2024-01-01'),
'file2.txt': new Date('2024-01-02'),
'file3.txt': new Date('2024-01-03'),
'file4.txt': new Date('2024-01-04'),
'file5.txt': new Date('2024-01-05'),
};
return {
isDirectory: () => false,
birthtime: new Date('2024-01-01'),
mtime: dates[name!] || new Date('2024-01-01'),
atime: new Date('2024-01-20'),
size: 1024,
} as any;
});
// Sort by modifiedTime desc (default) and limit to 3
const result = await localFileCtr.listLocalFiles({
path: '/test',
limit: 3,
});
// Should get the 3 newest files
expect(result.files).toHaveLength(3);
expect(result.totalCount).toBe(5); // Total is 5, but limited to 3
expect(result.files.map((r) => r.name)).toEqual(['file5.txt', 'file4.txt', 'file3.txt']);
});
it('should handle limit larger than file count', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue(['file1.txt', 'file2.txt']);
vi.mocked(mockFsPromises.stat).mockResolvedValue({
isDirectory: () => false,
birthtime: new Date('2024-01-01'),
mtime: new Date('2024-01-15'),
atime: new Date('2024-01-20'),
size: 1024,
} as any);
const result = await localFileCtr.listLocalFiles({
path: '/test',
limit: 1000,
});
expect(result.files).toHaveLength(2);
expect(result.totalCount).toBe(2);
});
it('should return file metadata including size, times and type', async () => {
const createdTime = new Date('2024-01-01');
const modifiedTime = new Date('2024-01-15');
const accessTime = new Date('2024-01-20');
vi.mocked(mockFsPromises.readdir).mockResolvedValue(['document.pdf']);
vi.mocked(mockFsPromises.stat).mockResolvedValue({
isDirectory: () => false,
birthtime: createdTime,
mtime: modifiedTime,
atime: accessTime,
size: 2048,
} as any);
const result = await localFileCtr.listLocalFiles({ path: '/test' });
expect(result.files).toHaveLength(1);
expect(result.totalCount).toBe(1);
expect(result.files[0]).toEqual({
name: 'document.pdf',
path: '/test/document.pdf',
isDirectory: false,
size: 2048,
type: 'pdf',
createdTime,
modifiedTime,
lastAccessTime: accessTime,
});
});
it('should return empty result when directory read fails', async () => {
vi.mocked(mockFsPromises.readdir).mockRejectedValue(new Error('Permission denied'));
const result = await localFileCtr.listLocalFiles({ path: '/protected' });
expect(result.files).toEqual([]);
expect(result.totalCount).toBe(0);
});
it('should skip files that cannot be stat', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue(['good.txt', 'bad.txt']);
vi.mocked(mockFsPromises.stat).mockImplementation(async (filePath) => {
if ((filePath as string).includes('bad.txt')) {
throw new Error('Cannot stat file');
}
return {
isDirectory: () => false,
birthtime: new Date('2024-01-01'),
mtime: new Date('2024-01-15'),
atime: new Date('2024-01-20'),
size: 1024,
} as any;
});
const result = await localFileCtr.listLocalFiles({ path: '/test' });
// Should only contain good.txt, bad.txt should be skipped
expect(result.files).toHaveLength(1);
expect(result.totalCount).toBe(1);
expect(result.files[0].name).toBe('good.txt');
});
it('should handle directory type correctly', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue(['my_folder']);
vi.mocked(mockFsPromises.stat).mockResolvedValue({
isDirectory: () => true,
birthtime: new Date('2024-01-01'),
mtime: new Date('2024-01-15'),
atime: new Date('2024-01-20'),
size: 4096,
} as any);
const result = await localFileCtr.listLocalFiles({ path: '/test' });
expect(result.files).toHaveLength(1);
expect(result.totalCount).toBe(1);
expect(result.files[0].isDirectory).toBe(true);
expect(result.files[0].type).toBe('directory');
});
it('should handle files without extension', async () => {
vi.mocked(mockFsPromises.readdir).mockResolvedValue(['Makefile', 'README']);
vi.mocked(mockFsPromises.stat).mockResolvedValue({
isDirectory: () => false,
birthtime: new Date('2024-01-01'),
mtime: new Date('2024-01-15'),
atime: new Date('2024-01-20'),
size: 512,
} as any);
const result = await localFileCtr.listLocalFiles({ path: '/test' });
expect(result.files).toHaveLength(2);
expect(result.totalCount).toBe(2);
// Files without extension should have empty type
expect(result.files[0].type).toBe('');
expect(result.files[1].type).toBe('');
});
});
describe('handleGrepContent', () => {
it('should search content in a single file', async () => {
vi.mocked(mockFsPromises.stat).mockResolvedValue({
+68
View File
@@ -1,4 +1,72 @@
[
{
"children": {
"improvements": ["Improve local-system tool implement."]
},
"date": "2026-02-01",
"version": "2.1.6"
},
{
"children": {
"fixes": ["Slove the group member agents cant set skills problem."]
},
"date": "2026-01-31",
"version": "2.1.5"
},
{
"children": {
"improvements": ["Update i18n, Update Kimi K2.5 & Qwen3 Max Thinking models."]
},
"date": "2026-01-31",
"version": "2.1.4"
},
{
"children": {},
"date": "2026-01-31",
"version": "2.1.3"
},
{
"children": {
"fixes": ["Fix feishu sso provider."]
},
"date": "2026-01-30",
"version": "2.1.2"
},
{
"children": {
"fixes": ["Correct desktop download URL path."]
},
"date": "2026-01-30",
"version": "2.1.1"
},
{
"children": {
"features": ["Refactor cron job UI and use runtime enableBusinessFeatures flag."]
},
"date": "2026-01-30",
"version": "2.1.0"
},
{
"children": {
"improvements": ["Fix usage table display issues."]
},
"date": "2026-01-29",
"version": "2.0.13"
},
{
"children": {
"fixes": ["Group publish to market should set local group market identifer."]
},
"date": "2026-01-29",
"version": "2.0.12"
},
{
"children": {
"improvements": ["Fix group task render."]
},
"date": "2026-01-29",
"version": "2.0.11"
},
{
"children": {
"fixes": ["Add ExtendParamsTypeSchema for enhanced model settings."]
+37
View File
@@ -0,0 +1,37 @@
# Proxy, if you need it
# HTTP_PROXY=http://localhost:7890
# HTTPS_PROXY=http://localhost:7890
# Allowed email addresses for login, separated by commas
# When set, only emails in the list can log in, other users cannot log in
# Leave empty to allow all users to register
# AUTH_ALLOWED_EMAILS=user1@example.com,user2@example.com
# Disable user registration (SSO-only mode)
# When set to 1, users cannot register via email/password, only SSO login is allowed
# AUTH_DISABLE_EMAIL_PASSWORD=1
# ===========================
# ====== Preset config ======
# ===========================
# if no special requirements, no need to change
LOBE_PORT=3210
RUSTFS_PORT=9000
APP_URL=http://localhost:3210
# INTERNAL_APP_URL is optional, used for server-to-server calls
# to bypass CDN/proxy. If not set, defaults to APP_URL.
# Example: INTERNAL_APP_URL=http://localhost:3210
# Postgres related, which are the necessary environment variables for DB
LOBE_DB_NAME=lobechat
POSTGRES_PASSWORD=uWNZugjBqixf8dxC
# RUSTFS S3 configuration
RUSTFS_ACCESS_KEY=admin
RUSTFS_SECRET_KEY=YOUR_RUSTFS_PASSWORD
# Configure the bucket information of RUSTFS
S3_ENDPOINT=http://localhost:9000
RUSTFS_LOBE_BUCKET=lobe
JWKS_KEY={"keys":[{"d":"PVoFyqyrGstB8wU52S7gqqQQdZLtin_thcEM0nrNtqp9U-NlKLlhgEcWp5t89ycgvhsAzmrRbezGj4JBTr3jn7eWdwQpPJNYiipnsgeJn0pwsB0H2dMqtavxinoPVXkMTOuGHMTFhhyguFBw2JbIL0PTQUcUlXjv40OoJpYHZeggSxgfV-TuxjwW8Ll4-n84M5IOi6A53RvioE-Hm1iyIc2XLBCfyOu-SbAQYi8HzrA64kCxobAB0peLQMiAzfZmwPKiGOhnhKrAlYmG02qFnbUYiJu_-AXwsAyGv9S9i6dwK7QXaGGWYyis8LlPpd_JmPrBnrWomwDlI045NUMWZQ","dp":"OSXI2NBBZl2r0Dpf4-1z44A_jC5lOyXtJhXQYnSXy5eIuxTJcEtkUYagGEwnREO4Q3t-4J-lT_6Y71M1ZlgKG1upwfw1O4aE3vGpHOik9iZYYCjA8fe5uBfOpX1ELmOtHNoHRhMtyjuPxSFXLlSp3bgcF1f3F40ClukdvXCx0Mc","dq":"m6hNdfj-F8E_7nUlX2nG95OffkFrhHTo67ML9aPgpvFwBlzg-hk5LwtxMfUzngqWF78TMl0JDm7vS1bz0xlWqXqu8pFPoTUnUoWgYfvuyHLBwR5TgccQkfoKbkSMzYNy8VJPXZeyIjVXsW98tZvj-NZF-M9Pke_EWJm-jjXCu_8","e":"AQAB","kty":"RSA","n":"piffosMS0HOSgsSr_zQkXYaQt1kOCD73VR0b2XJD6UdQCKPbnBOzTIuA_xowX61QVsl5pCZLTw8ERC3r2Nlxj5Rp_H6RuOT7ioUqlbnxSGnfuAn8dFupY3A-sf9HVDOvtJdlS-nO9yA4wWU-A50zZ1Mf0pPZlUZE6dUQfsJFi5yXaNAybyk3U4VpMO_SXAilWEHVhiO0F0ccpJMCkT47AeXmYH9MlWwIGcay0UiAsdrs8J-q1arZ7Mbq0oxHmUXJG0vwRvAL8KnCEi8cJ3e2kKCRcr-BQCujsHUyUl6f_ATwSVuTHdAR1IzIcW37v27h3WQK_v0ffQM1NstamDX5vQ","p":"4myVm2M5cZGvVXsOmWUTUG87VC1GlQcL5tmMNSGSpQCL8yWZ1vANkmCxSMptrKB4dU9DAB3On6_oMhW1pJ3uYNGSW49BcmJoLkiWKeg5zWFnKPQNuThQmY1sCCubtKhBQgaYUr7TVzN9smrDV3zCu9MlRl-XPwnEmWaDII3g-f8","q":"u9v4IOEsb4l2Y3eWKE2bwJh5fJRR4vivaYA7U-1-OpvDwB3A48Rey9IL1ucXqE5G1Du8BtijPm5oSAar5uzrjtg1bZ9gevif6DnBGaIRE7LnSrUsTPfZwzntJ1rTaGiVe_pAdnTKXXaH6DxygXxH4wvGgA44V3TTfBXQUcjzdEM","qi":"lDBnSPKkRnYqQvbqVD1LxzqBPEeqEA3GyCqMj6fIZNgoEaBSLi0TSsUyGZ5mahX3KO35vKAZa5jvGjhvUGUiXycq8KvRZdeGK45vJdwZT2TiXiDwo9IQgJcbFMpxaB9DhjX2x0yqxgUY5ca75jLqbMuKBKBN0PVqIr9jlHkR8_s","use":"sig","kid":"6823046760c5d460","alg":"RS256"}]}
+34
View File
@@ -0,0 +1,34 @@
# Proxy,如果你需要的话(比如你使用 GitHub 作为鉴权服务提供商)
# HTTP_PROXY=http://localhost:7890
# HTTPS_PROXY=http://localhost:7890
# 允许登录的邮箱地址,用英文逗号分隔
# 设置后只有列表中的邮箱可以登录,其他用户可以注册但无法登录
# 留空则允许所有用户注册登录
# AUTH_ALLOWED_EMAILS=user1@example.com,user2@example.com
# 禁用用户注册(仅允许 SSO 登录)
# 设置为 1 后,用户无法通过邮箱密码注册,只能通过 SSO 登录
# AUTH_DISABLE_EMAIL_PASSWORD=1
# ===================
# ===== 预设配置 =====
# ===================
# 如没有特殊需要不用更改
LOBE_PORT=3210
RUSTFS_PORT=9000
APP_URL=http://localhost:3210
# Postgres 相关,也即 DB 必须的环境变量
LOBE_DB_NAME=lobehub
POSTGRES_PASSWORD=uWNZugjBqixf8dxC
# RustFS S3 配置
RUSTFS_ACCESS_KEY=admin
RUSTFS_SECRET_KEY=YOUR_RUSTFS_PASSWORD
# 在下方配置 rustfs 中添加的桶
S3_ENDPOINT=http://localhost:9000
RUSTFS_LOBE_BUCKET=lobe
JWKS_KEY={"keys":[{"d":"PVoFyqyrGstB8wU52S7gqqQQdZLtin_thcEM0nrNtqp9U-NlKLlhgEcWp5t89ycgvhsAzmrRbezGj4JBTr3jn7eWdwQpPJNYiipnsgeJn0pwsB0H2dMqtavxinoPVXkMTOuGHMTFhhyguFBw2JbIL0PTQUcUlXjv40OoJpYHZeggSxgfV-TuxjwW8Ll4-n84M5IOi6A53RvioE-Hm1iyIc2XLBCfyOu-SbAQYi8HzrA64kCxobAB0peLQMiAzfZmwPKiGOhnhKrAlYmG02qFnbUYiJu_-AXwsAyGv9S9i6dwK7QXaGGWYyis8LlPpd_JmPrBnrWomwDlI045NUMWZQ","dp":"OSXI2NBBZl2r0Dpf4-1z44A_jC5lOyXtJhXQYnSXy5eIuxTJcEtkUYagGEwnREO4Q3t-4J-lT_6Y71M1ZlgKG1upwfw1O4aE3vGpHOik9iZYYCjA8fe5uBfOpX1ELmOtHNoHRhMtyjuPxSFXLlSp3bgcF1f3F40ClukdvXCx0Mc","dq":"m6hNdfj-F8E_7nUlX2nG95OffkFrhHTo67ML9aPgpvFwBlzg-hk5LwtxMfUzngqWF78TMl0JDm7vS1bz0xlWqXqu8pFPoTUnUoWgYfvuyHLBwR5TgccQkfoKbkSMzYNy8VJPXZeyIjVXsW98tZvj-NZF-M9Pke_EWJm-jjXCu_8","e":"AQAB","kty":"RSA","n":"piffosMS0HOSgsSr_zQkXYaQt1kOCD73VR0b2XJD6UdQCKPbnBOzTIuA_xowX61QVsl5pCZLTw8ERC3r2Nlxj5Rp_H6RuOT7ioUqlbnxSGnfuAn8dFupY3A-sf9HVDOvtJdlS-nO9yA4wWU-A50zZ1Mf0pPZlUZE6dUQfsJFi5yXaNAybyk3U4VpMO_SXAilWEHVhiO0F0ccpJMCkT47AeXmYH9MlWwIGcay0UiAsdrs8J-q1arZ7Mbq0oxHmUXJG0vwRvAL8KnCEi8cJ3e2kKCRcr-BQCujsHUyUl6f_ATwSVuTHdAR1IzIcW37v27h3WQK_v0ffQM1NstamDX5vQ","p":"4myVm2M5cZGvVXsOmWUTUG87VC1GlQcL5tmMNSGSpQCL8yWZ1vANkmCxSMptrKB4dU9DAB3On6_oMhW1pJ3uYNGSW49BcmJoLkiWKeg5zWFnKPQNuThQmY1sCCubtKhBQgaYUr7TVzN9smrDV3zCu9MlRl-XPwnEmWaDII3g-f8","q":"u9v4IOEsb4l2Y3eWKE2bwJh5fJRR4vivaYA7U-1-OpvDwB3A48Rey9IL1ucXqE5G1Du8BtijPm5oSAar5uzrjtg1bZ9gevif6DnBGaIRE7LnSrUsTPfZwzntJ1rTaGiVe_pAdnTKXXaH6DxygXxH4wvGgA44V3TTfBXQUcjzdEM","qi":"lDBnSPKkRnYqQvbqVD1LxzqBPEeqEA3GyCqMj6fIZNgoEaBSLi0TSsUyGZ5mahX3KO35vKAZa5jvGjhvUGUiXycq8KvRZdeGK45vJdwZT2TiXiDwo9IQgJcbFMpxaB9DhjX2x0yqxgUY5ca75jLqbMuKBKBN0PVqIr9jlHkR8_s","use":"sig","kid":"6823046760c5d460","alg":"RS256"}]}
+18
View File
@@ -0,0 +1,18 @@
{
"ID": "",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": ["*"]
},
"Action": ["s3:GetObject"],
"NotAction": [],
"Resource": ["arn:aws:s3:::lobe/*"],
"NotResource": [],
"Condition": {}
}
],
"Version": "2012-10-17"
}
+148
View File
@@ -0,0 +1,148 @@
name: lobehub
services:
network-service:
image: alpine
container_name: lobe-network
restart: always
ports:
- '${RUSTFS_PORT}:9000' # RustFS API
- '9001:9001' # RustFS Console
- '${LOBE_PORT}:3210' # LobeChat
command: tail -f /dev/null
networks:
- lobe-network
postgresql:
image: paradedb/paradedb:latest-pg17
container_name: lobe-postgres
ports:
- '5432:5432'
volumes:
- './data:/var/lib/postgresql/data'
environment:
- 'POSTGRES_DB=${LOBE_DB_NAME}'
- 'POSTGRES_PASSWORD=${POSTGRES_PASSWORD}'
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U postgres']
interval: 5s
timeout: 5s
retries: 5
restart: always
networks:
- lobe-network
redis:
image: redis:7-alpine
container_name: lobe-redis
ports:
- '6379:6379'
command: redis-server --save 60 1000 --appendonly yes
volumes:
- 'redis_data:/data'
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 5s
timeout: 3s
retries: 5
restart: always
networks:
- lobe-network
rustfs:
image: rustfs/rustfs:latest
container_name: lobe-rustfs
network_mode: 'service:network-service'
environment:
- RUSTFS_CONSOLE_ENABLE=true
- RUSTFS_ACCESS_KEY=${RUSTFS_ACCESS_KEY}
- RUSTFS_SECRET_KEY=${RUSTFS_SECRET_KEY}
volumes:
- rustfs-data:/data
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:9000/health >/dev/null 2>&1 || exit 1"]
interval: 5s
timeout: 3s
retries: 30
command: ["--access-key","${RUSTFS_ACCESS_KEY}","--secret-key","${RUSTFS_SECRET_KEY}","/data"]
rustfs-init:
image: minio/mc:latest
container_name: lobe-rustfs-init
depends_on:
rustfs:
condition: service_healthy
volumes:
- ./bucket.config.json:/bucket.config.json:ro
entrypoint: /bin/sh
command: -c '
set -eux;
echo "S3_ACCESS_KEY=${RUSTFS_ACCESS_KEY}, S3_SECRET_KEY=${RUSTFS_SECRET_KEY}";
mc --version;
mc alias set rustfs "http://network-service:9000" "${RUSTFS_ACCESS_KEY}" "${RUSTFS_SECRET_KEY}";
mc ls rustfs || true;
mc mb "rustfs/lobe" --ignore-existing;
mc admin info rustfs || true;
mc anonymous set-json "/bucket.config.json" "rustfs/lobe";
'
restart: "no"
networks:
- lobe-network
searxng:
image: searxng/searxng
container_name: lobe-searxng
volumes:
- './searxng-settings.yml:/etc/searxng/settings.yml'
environment:
- 'SEARXNG_SETTINGS_FILE=/etc/searxng/settings.yml'
restart: always
networks:
- lobe-network
env_file:
- .env
lobe:
image: lobehub/lobehub
container_name: lobehub
network_mode: 'service:network-service'
depends_on:
postgresql:
condition: service_healthy
network-service:
condition: service_started
rustfs:
condition: service_healthy
rustfs-init:
condition: service_completed_successfully
redis:
condition: service_healthy
environment:
- 'KEY_VAULTS_SECRET=Kix2wcUONd4CX51E/ZPAd36BqM4wzJgKjPtz2sGztqQ='
- 'AUTH_SECRET=NX2kaPE923dt6BL2U8e9oSre5RfoT7hg'
- 'DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgresql:5432/${LOBE_DB_NAME}'
- 'S3_BUCKET=${RUSTFS_LOBE_BUCKET}'
- 'S3_ENABLE_PATH_STYLE=1'
- 'S3_ACCESS_KEY=${RUSTFS_ACCESS_KEY}'
- 'S3_ACCESS_KEY_ID=${RUSTFS_ACCESS_KEY}'
- 'S3_SECRET_ACCESS_KEY=${RUSTFS_SECRET_KEY}'
- 'LLM_VISION_IMAGE_USE_BASE64=1'
- 'S3_SET_ACL=0'
- 'SEARXNG_URL=http://searxng:8080'
- 'REDIS_URL=redis://redis:6379'
- 'REDIS_PREFIX=lobechat'
- 'REDIS_TLS=0'
env_file:
- .env
restart: always
volumes:
data:
driver: local
redis_data:
driver: local
rustfs-data:
driver: local
networks:
lobe-network:
driver: bridge
File diff suppressed because it is too large Load Diff
-1
View File
@@ -37,7 +37,6 @@ RUSTFS_ACCESS_KEY=admin
RUSTFS_SECRET_KEY=YOUR_RUSTFS_PASSWORD
# Configure the bucket information of RUSTFS
S3_PUBLIC_DOMAIN=http://localhost:9000
S3_ENDPOINT=http://localhost:9000
RUSTFS_LOBE_BUCKET=lobe
-1
View File
@@ -34,7 +34,6 @@ RUSTFS_ACCESS_KEY=admin
RUSTFS_SECRET_KEY=YOUR_RUSTFS_PASSWORD
# 在下方配置 rustfs 中添加的桶
S3_PUBLIC_DOMAIN=http://localhost:9000
S3_ENDPOINT=http://localhost:9000
RUSTFS_LOBE_BUCKET=lobe
@@ -34,7 +34,6 @@ MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=YOUR_MINIO_PASSWORD
# Configure the bucket information of MinIO
S3_PUBLIC_DOMAIN=http://localhost:9000
S3_ENDPOINT=http://localhost:9000
MINIO_LOBE_BUCKET=lobe
@@ -34,7 +34,6 @@ MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=YOUR_MINIO_PASSWORD
# 在下方配置 minio 中添加的桶
S3_PUBLIC_DOMAIN=http://localhost:9000
S3_ENDPOINT=http://localhost:9000
MINIO_LOBE_BUCKET=lobe
@@ -103,7 +103,6 @@ services:
- 'DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgresql:5432/${LOBE_DB_NAME}'
- 'S3_ENDPOINT=http://localhost:${MINIO_PORT}'
- 'S3_BUCKET=${MINIO_LOBE_BUCKET}'
- 'S3_PUBLIC_DOMAIN=http://localhost:${MINIO_PORT}'
- 'S3_ENABLE_PATH_STYLE=1'
- 'REDIS_URL=redis://redis:6379'
- 'REDIS_PREFIX=lobechat'
+1 -2
View File
@@ -21,8 +21,7 @@ AUTH_ZITADEL_ISSUER=http://localhost:8080
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
S3_ENDPOINT=http://localhost:9000
S3_BUCKET=lobe
S3_PUBLIC_DOMAIN=http://localhost:9000
S3_BUCKET=lobe
S3_ENABLE_PATH_STYLE=1
LLM_VISION_IMAGE_USE_BASE64=1
@@ -20,8 +20,7 @@ AUTH_ZITADEL_ISSUER=http://localhost:8080
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
S3_ENDPOINT=http://localhost:9000
S3_BUCKET=lobe
S3_PUBLIC_DOMAIN=http://localhost:9000
S3_BUCKET=lobe
S3_ENABLE_PATH_STYLE=1
LLM_VISION_IMAGE_USE_BASE64=1
@@ -34,7 +34,6 @@ MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=YOUR_MINIO_PASSWORD
# Configure the bucket information of MinIO
S3_PUBLIC_DOMAIN=http://localhost:9000
S3_ENDPOINT=http://localhost:9000
MINIO_LOBE_BUCKET=lobe
@@ -34,7 +34,6 @@ MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=YOUR_MINIO_PASSWORD
# 在下方配置 minio 中添加的桶
S3_PUBLIC_DOMAIN=http://localhost:9000
S3_ENDPOINT=http://localhost:9000
MINIO_LOBE_BUCKET=lobe
@@ -38,8 +38,6 @@ S3_SECRET_ACCESS_KEY=YOUR_S3_SECRET_ACCESS_KEY
S3_ENDPOINT=https://lobe-s3-api.example.com
# Required: S3 Bucket (invalid until manually created in MinIO UI)
S3_BUCKET=lobe
# Required: S3 Public Domain for client access to unstructured data
S3_PUBLIC_DOMAIN=https://lobe-s3-api.example.com
# Optional: S3 Enable Path Style
# Use 0 for mainstream S3 cloud providers; use 1 for self-hosted MinIO
# See: https://lobehub.com/docs/self-hosting/advanced/s3#s-3-enable-path-style
@@ -38,8 +38,6 @@ S3_SECRET_ACCESS_KEY=YOUR_S3_SECRET_ACCESS_KEY
S3_ENDPOINT=https://lobe-s3-api.example.com
# 必填,S3 的 Bucket,直到在 MinIO UI 中手动创建之前都是无效的
S3_BUCKET=lobe
# 必填,S3 的 Public Domain,用于客户端通过公开连接访问非结构化数据
S3_PUBLIC_DOMAIN=https://lobe-s3-api.example.com
# 选填,S3 的 Enable Path Style
# 对于主流 S3 Cloud 服务商,一般填 0 即可;对于自部署的 MinIO,请填 1
# 请参考:https://lobehub.com/zh/docs/self-hosting/advanced/s3#s-3-enable-path-style
@@ -35,8 +35,6 @@ S3_SECRET_ACCESS_KEY=YOUR_S3_SECRET_ACCESS_KEY
S3_ENDPOINT=https://lobe-s3-api.example.com
# Required: S3 Bucket (invalid until manually created in MinIO UI)
S3_BUCKET=lobe
# Required: S3 Public Domain for client access to unstructured data
S3_PUBLIC_DOMAIN=https://lobe-s3-api.example.com
# Optional: S3 Enable Path Style
# Use 0 for mainstream S3 cloud providers; use 1 for self-hosted MinIO
# See: https://lobehub.com/docs/self-hosting/advanced/s3#s-3-enable-path-style
@@ -31,8 +31,6 @@ S3_SECRET_ACCESS_KEY=YOUR_S3_SECRET_ACCESS_KEY
S3_ENDPOINT=https://lobe-s3-api.example.com
# 必填,S3 的 Bucket,直到在 MinIO UI 中手动创建之前都是无效的
S3_BUCKET=lobe
# 必填,S3 的 Public Domain,用于客户端通过公开连接访问非结构化数据
S3_PUBLIC_DOMAIN=https://lobe-s3-api.example.com
# 选填,S3 的 Enable Path Style
# 对于主流 S3 Cloud 服务商,一般填 0 即可;对于自部署的 MinIO,请填 1
# 请参考:https://lobehub.com/zh/docs/self-hosting/advanced/s3#s-3-enable-path-style
+53 -90
View File
@@ -230,6 +230,20 @@ show_message() {
;;
esac
;;
tips_disable_registration)
case $LANGUAGE in
zh_CN)
echo "如需限制用户注册,可在 .env 中配置:"
echo " - 使用 SSO 登录时,设置 AUTH_DISABLE_EMAIL_PASSWORD=1 可禁用邮箱密码注册"
echo " - 使用邮箱密码登录时,设置 AUTH_ALLOWED_EMAILS=user1@example.com,user2@example.com 可限制允许登录的邮箱"
;;
*)
echo "To restrict user registration, configure in .env:"
echo " - For SSO login: set AUTH_DISABLE_EMAIL_PASSWORD=1 to disable email/password registration"
echo " - For email/password login: set AUTH_ALLOWED_EMAILS=user1@example.com,user2@example.com to allow specific emails"
;;
esac
;;
tips_show_documentation)
case $LANGUAGE in
zh_CN)
@@ -263,10 +277,10 @@ show_message() {
tips_allow_ports)
case $LANGUAGE in
zh_CN)
echo "请确保服务器以下端口未被占用且能被访问:3210, 9000, 9001, 8000"
echo "请确保服务器以下端口未被占用且能被访问:3210, 9000, 9001"
;;
*)
echo "Please make sure the following ports on the server are not occupied and can be accessed: 3210, 9000, 9001, 8000"
echo "Please make sure the following ports on the server are not occupied and can be accessed: 3210, 9000, 9001"
;;
esac
;;
@@ -315,12 +329,10 @@ show_message() {
tips_init_database_failed)
case $LANGUAGE in
zh_CN)
echo "无法初始化数据库,为了避免你的数据重复初始化,请在首次成功启动时运行以下指令清空 Casdoor 初始配置文件:"
echo "echo '{}' > init_data.json"
echo "无法初始化数据库"
;;
*)
echo "Failed to initialize the database. To avoid your data being initialized repeatedly, run the following command to unmount the initial configuration file of Casdoor when you first start successfully:"
echo "echo '{}' > init_data.json"
echo "Failed to initialize the database."
;;
esac
;;
@@ -338,7 +350,7 @@ show_message() {
case $LANGUAGE in
zh_CN)
echo "请选择部署模式:"
echo "(0) 域名模式(访问时无需指明端口),需要使用反向代理服务 LobeHub, RustFS, Casdoor ,并分别分配一个域名;"
echo "(0) 域名模式(访问时无需指明端口),需要使用反向代理服务 LobeHub, RustFS,并分别分配一个域名;"
echo "(1) 端口模式(访问时需要指明端口,如使用IP访问,或域名+端口访问),需要放开指定端口;"
echo "(2) 本地模式(仅供本地测试使用)"
echo "如果你对这些内容疑惑,可以先选择使用本地模式进行部署,稍后根据文档指引再进行修改。"
@@ -346,7 +358,7 @@ show_message() {
;;
*)
echo "Please select the deployment mode:"
echo "(0) Domain mode (no need to specify the port when accessing), you need to use the reverse proxy service LobeHub, RustFS, Casdoor, and assign a domain name respectively;"
echo "(0) Domain mode (no need to specify the port when accessing), you need to use the reverse proxy service LobeHub, RustFS, and assign a domain name respectively;"
echo "(1) Port mode (need to specify the port when accessing, such as using IP access, or domain name + port access), you need to open the specified port;"
echo "(2) Local mode (for local testing only)"
echo "If you are confused about these contents, you can choose to deploy in local mode first, and then modify according to the document guide later."
@@ -408,31 +420,33 @@ download_file() {
}
print_centered() {
# Define colors
declare -A colors
colors=(
[black]="\e[30m"
[red]="\e[31m"
[green]="\e[32m"
[yellow]="\e[33m"
[blue]="\e[34m"
[magenta]="\e[35m"
[cyan]="\e[36m"
[white]="\e[37m"
[reset]="\e[0m"
)
local text="$1" # Get input texts
local color="${2:-reset}" # Get color, default to reset
local term_width=$(tput cols) # Get terminal width
local text_length=${#text} # Get text length
local padding=$(((term_width - text_length) / 2)) # Get padding
# Check if the color is valid
if [[ -z "${colors[$color]}" ]]; then
echo "Invalid color specified. Available colors: ${!colors[@]}"
return 1
fi
# Get color code (compatible with bash 3.x)
local color_code=""
local reset_code="\e[0m"
case "$color" in
black) color_code="\e[30m" ;;
red) color_code="\e[31m" ;;
green) color_code="\e[32m" ;;
yellow) color_code="\e[33m" ;;
blue) color_code="\e[34m" ;;
magenta) color_code="\e[35m" ;;
cyan) color_code="\e[36m" ;;
white) color_code="\e[37m" ;;
reset) color_code="\e[0m" ;;
*)
echo "Invalid color specified. Available colors: black red green yellow blue magenta cyan white reset"
return 1
;;
esac
# Print the text with padding
printf "%*s${colors[$color]}%s${colors[reset]}\n" $padding "" "$text"
printf "%*s${color_code}%s${reset_code}\n" $padding "" "$text"
}
# Usage:
@@ -469,10 +483,9 @@ ask() {
# == Variables ==
# ===============
# File list
SUB_DIR="docker-compose/local"
SUB_DIR="docker-compose/deploy"
FILES=(
"$SUB_DIR/docker-compose.yml"
"$SUB_DIR/init_data.json"
"$SUB_DIR/searxng-settings.yml"
"$SUB_DIR/bucket.config.json"
)
@@ -481,10 +494,7 @@ ENV_EXAMPLES=(
"$SUB_DIR/.env.example"
)
# Default values
CASDOOR_PASSWORD="pswd123"
CASDOOR_SECRET="CASDOOR_SECRET"
RUSTFS_SECRET_KEY="YOUR_RUSTFS_PASSWORD"
CASDOOR_HOST="localhost:8000"
RUSTFS_HOST="localhost:9000"
PROTOCOL="http"
@@ -514,9 +524,8 @@ section_download_files(){
fi
download_file "$SOURCE_URL/${FILES[0]}" "docker-compose.yml"
download_file "$SOURCE_URL/${FILES[1]}" "init_data.json"
download_file "$SOURCE_URL/${FILES[2]}" "searxng-settings.yml"
download_file "$SOURCE_URL/${FILES[3]}" "bucket.config.json"
download_file "$SOURCE_URL/${FILES[1]}" "searxng-settings.yml"
download_file "$SOURCE_URL/${FILES[2]}" "bucket.config.json"
# Download .env.example with the specified language
if [ "$LANGUAGE" = "zh_CN" ]; then
download_file "$SOURCE_URL/${ENV_EXAMPLES[0]}" ".env"
@@ -576,15 +585,10 @@ section_configurate_host() {
echo "LobeHub" $(show_message "ask_domain" "example.com")
ask "(example.com)"
LOBE_HOST="$ask_result"
# If user use domain mode, ask for the domain of RustFS and Casdoor
# If user use domain mode, ask for the domain of RustFS
echo "RustFS S3 API" $(show_message "ask_domain" "s3.example.com")
ask "(s3.example.com)"
RUSTFS_HOST="$ask_result"
echo "Casdoor API" $(show_message "ask_domain" "auth.example.com")
ask "(auth.example.com)"
CASDOOR_HOST="$ask_result"
# Setup callback url for Casdoor
sed "${SED_INPLACE_ARGS[@]}" "s/"example.com"/${LOBE_HOST}/" init_data.json
;;
1)
DEPLOY_MODE="ip"
@@ -595,23 +599,16 @@ section_configurate_host() {
# If user use ip mode, append the port to the host
LOBE_HOST="${HOST}:3210"
RUSTFS_HOST="${HOST}:9000"
CASDOOR_HOST="${HOST}:8000"
# Setup callback url for Casdoor
sed "${SED_INPLACE_ARGS[@]}" "s/"localhost:3210"/${LOBE_HOST}/" init_data.json
;;
*)
echo "Invalid deploy mode: $ask_result"
exit 1
;;
esac
# lobe host
sed "${SED_INPLACE_ARGS[@]}" "s#^APP_URL=.*#APP_URL=$PROTOCOL://$LOBE_HOST#" .env
# auth related
sed "${SED_INPLACE_ARGS[@]}" "s#^AUTH_CASDOOR_ISSUER=.*#AUTH_CASDOOR_ISSUER=$PROTOCOL://$CASDOOR_HOST#" .env
sed "${SED_INPLACE_ARGS[@]}" "s#^origin=.*#origin=$PROTOCOL://$CASDOOR_HOST#" .env
# s3 related
sed "${SED_INPLACE_ARGS[@]}" "s#^S3_PUBLIC_DOMAIN=.*#S3_PUBLIC_DOMAIN=$PROTOCOL://$RUSTFS_HOST#" .env
sed "${SED_INPLACE_ARGS[@]}" "s#^S3_ENDPOINT=.*#S3_ENDPOINT=$PROTOCOL://$RUSTFS_HOST#" .env
@@ -664,37 +661,7 @@ section_regenerate_secrets() {
exit 1
fi
echo $(show_message "security_secrect_regenerate")
# Generate CASDOOR_SECRET
CASDOOR_SECRET=$(generate_key 32)
if [ $? -ne 0 ]; then
echo $(show_message "security_secrect_regenerate_failed") "CASDOOR_SECRET"
else
# Search and replace the value of CASDOOR_SECRET in .env
sed "${SED_INPLACE_ARGS[@]}" "s#^AUTH_CASDOOR_SECRET=.*#AUTH_CASDOOR_SECRET=${CASDOOR_SECRET}#" .env
if [ $? -ne 0 ]; then
echo $(show_message "security_secrect_regenerate_failed") "AUTH_CASDOOR_SECRET in \`.env\`"
fi
# replace `clientSecrect` in init_data.json
sed "${SED_INPLACE_ARGS[@]}" "s#dbf205949d704de81b0b5b3603174e23fbecc354#${CASDOOR_SECRET}#" init_data.json
if [ $? -ne 0 ]; then
echo $(show_message "security_secrect_regenerate_failed") "AUTH_CASDOOR_SECRET in \`init_data.json\`"
fi
fi
# Generate Casdoor User
CASDOOR_USER="admin"
CASDOOR_PASSWORD=$(generate_key 10)
if [ $? -ne 0 ]; then
echo $(show_message "security_secrect_regenerate_failed") "CASDOOR_PASSWORD"
CASDOOR_PASSWORD="pswd123"
else
# replace `password` in init_data.json
sed "${SED_INPLACE_ARGS[@]}" "s/"pswd123"/${CASDOOR_PASSWORD}/" init_data.json
if [ $? -ne 0 ]; then
echo $(show_message "security_secrect_regenerate_failed") "CASDOOR_PASSWORD in \`init_data.json\`"
fi
fi
# Generate RUSTFS S3 User Password
RUSTFS_SECRET_KEY=$(generate_key 8)
if [ $? -ne 0 ]; then
@@ -735,13 +702,10 @@ section_init_database() {
fi
docker compose pull
docker compose up --detach postgresql casdoor
docker compose up --detach postgresql
# hopefully enough time for even the slower systems
sleep 15
docker compose stop
# Init finished, remove init mount
echo '{}' > init_data.json
}
show_message "ask_init_database"
@@ -759,16 +723,14 @@ fi
section_display_configurated_report() {
# Display configuration reports
echo $(show_message "security_secrect_regenerate_report")
echo -e "LobeHub: \n - URL: $PROTOCOL://$LOBE_HOST \n - Username: user \n - Password: ${CASDOOR_PASSWORD} "
echo -e "Casdoor: \n - URL: $PROTOCOL://$CASDOOR_HOST \n - Username: admin \n - Password: ${CASDOOR_PASSWORD}\n"
echo -e "LobeHub: \n - URL: $PROTOCOL://$LOBE_HOST"
echo -e "RustFS: \n - URL: $PROTOCOL://$RUSTFS_HOST \n - Username: admin\n - Password: ${RUSTFS_SECRET_KEY}\n"
# if user run in domain mode, diplay reverse proxy configuration
if [[ "$DEPLOY_MODE" == "domain" ]]; then
echo $(show_message "tips_add_reverse_proxy")
printf "\n%s\t->\t%s\n" "$LOBE_HOST" "127.0.0.1:3210"
printf "%s\t->\t%s\n" "$CASDOOR_HOST" "127.0.0.1:8000"
printf "%s\t->\t%s\n" "$RUSTFS_HOST" "127.0.0.1:9000"
fi
@@ -777,7 +739,8 @@ section_display_configurated_report() {
printf "\n%s\n\n" "$(show_message "tips_run_command")"
print_centered "docker compose up --no-attach searxng" "green"
printf "\n%s\n" "$(show_message "tips_if_run_normally")"
printf "\n%s\n\n" "$(show_message "tips_regen_jwks")"
printf "\n%s\n" "$(show_message "tips_regen_jwks")"
printf "\n%s\n\n" "$(show_message "tips_disable_registration")"
print_centered "docker compose up -d --no-attach searxng" "green"
printf "\n%s\n" "$(show_message "tips_if_want_searxng_logs")"
print_centered "docker compose logs -f searxng" "white"
+1 -1
View File
@@ -9,7 +9,7 @@ tags:
# Seamless DeepSeek R1 Integration, Unlock a New Chain-of-Thought Experience
LobeChat completed its largest AI ecosystem expansion ever in February, delivering a more powerful and flexible AI chat experience.
LobeHub completed its largest AI ecosystem expansion ever in February, delivering a more powerful and flexible AI chat experience.
## 🌟 Major Updates
@@ -9,7 +9,7 @@ tags:
# 完美集成 DeepSeek R1 ,开启思维链新体验
LobeChat 在二月完成了史上最大规模的 AI 生态扩展,带来更强大、更灵活的 AI 对话体验。
LobeHub 在二月完成了史上最大规模的 AI 生态扩展,带来更强大、更灵活的 AI 对话体验。
## 🌟 重大更新
+1 -1
View File
@@ -9,7 +9,7 @@ tags:
# Seamless DeepSeek R1 Integration, Unlock a New Chain-of-Thought Experience
In March, LobeChat continued to refine the user experience—adding practical features like customizable hotkeys and data export, while further expanding the AI provider ecosystem.
In March, LobeHub continued to refine the user experience—adding practical features like customizable hotkeys and data export, while further expanding the AI provider ecosystem.
## 🌟 Key Updates
+1 -1
View File
@@ -9,7 +9,7 @@ tags:
# 完美集成 DeepSeek R1 ,开启思维链新体验
LobeChat 在三月持续优化用户体验,新增快捷键自定义、数据导出等实用功能,并扩展 AI 服务商生态。
LobeHub 在三月持续优化用户体验,新增快捷键自定义、数据导出等实用功能,并扩展 AI 服务商生态。
## 🌟 重要更新
+2 -2
View File
@@ -1,6 +1,6 @@
---
title: Brand-New Design Style and Desktop App Release ✨
description: LobeChat officially launches the desktop app, delivering a more modern and smoother experience.
description: LobeHub officially launches the desktop app, delivering a more modern and smoother experience.
tags:
- Desktop App
- LobeHub
@@ -9,7 +9,7 @@ tags:
# Brand-New Design Style and Desktop App Release ✨
In April, LobeChat shipped a major visual upgrade with the brand-new Lobe UI v2 design system, and officially released the desktop app—bringing a more modern and fluid experience.
In April, LobeHub shipped a major visual upgrade with the brand-new Lobe UI v2 design system, and officially released the desktop app—bringing a more modern and fluid experience.
## 🌟 Major Updates
@@ -1,6 +1,6 @@
---
title: 全新设计风格与桌面端发布 ✨
description: LobeChat 正式发布桌面端应用,带来更现代、更流畅的使用体验
description: LobeHub 正式发布桌面端应用,带来更现代、更流畅的使用体验
tags:
- 桌面端
- LobeHub
@@ -9,7 +9,7 @@ tags:
# 全新设计风格与桌面端发布 ✨
LobeChat 在四月完成重大视觉升级,推出全新 Lobe UI v2 设计系统,并正式发布桌面端应用,带来更现代、更流畅的使用体验。
LobeHub 在四月完成重大视觉升级,推出全新 Lobe UI v2 设计系统,并正式发布桌面端应用,带来更现代、更流畅的使用体验。
## 🌟 重大更新
+1 -1
View File
@@ -9,7 +9,7 @@ tags:
# Prompt Variables and Claude 4 Reasoning Model Support 🚀
From May to June, LobeChat continued to refine core capabilities—introducing a prompt-variables system, adding support for Claude 4 reasoning models, and expanding search and crawling across multiple AI providers.
From May to June, LobeHub continued to refine core capabilities—introducing a prompt-variables system, adding support for Claude 4 reasoning models, and expanding search and crawling across multiple AI providers.
## 🌟 Key Updates
+1 -1
View File
@@ -9,7 +9,7 @@ tags:
# 提示词变量与 Claude 4 推理模型支持 🚀
LobeChat 在五月至六月持续优化核心功能,新增提示词变量系统、支持 Claude 4 推理模型,并扩展多个 AI 服务商的搜索与推理能力。
LobeHub 在五月至六月持续优化核心功能,新增提示词变量系统、支持 Claude 4 推理模型,并扩展多个 AI 服务商的搜索与推理能力。
## 🌟 主要更新
+1 -1
View File
@@ -9,7 +9,7 @@ tags:
# MCP Marketplace and Search Provider Expansion 🔍
From June to July, LobeChat launched the MCP plugin marketplace, added support for multiple search providers, and integrated Amazon Cognito and Google SSO—continuing to improve both user experience and the developer ecosystem.
From June to July, LobeHub launched the MCP plugin marketplace, added support for multiple search providers, and integrated Amazon Cognito and Google SSO—continuing to improve both user experience and the developer ecosystem.
## 🌟 Major Updates
@@ -9,7 +9,7 @@ tags:
# MCP 市场与搜索服务商扩展 🔍
LobeChat 在六月至七月推出 MCP 插件市场,新增多个搜索服务商支持,并集成 Amazon Cognito 与 Google SSO 认证,持续优化用户体验与开发者生态。
LobeHub 在六月至七月推出 MCP 插件市场,新增多个搜索服务商支持,并集成 Amazon Cognito 与 Google SSO 认证,持续优化用户体验与开发者生态。
## 🌟 重大更新
@@ -9,7 +9,7 @@ tags:
# AI Image Generation and Desktop Enhancements 🎨
From July to August, LobeChat introduced AI image generation, added support for multiple providers, and continued improving the desktop experience and authentication system.
From July to August, LobeHub introduced AI image generation, added support for multiple providers, and continued improving the desktop experience and authentication system.
## 🌟 Major Updates
@@ -9,7 +9,7 @@ tags:
# AI 图像生成与桌面端增强 🎨
LobeChat 在七月至八月推出 AI 图像生成功能,新增多个服务商支持,并持续优化桌面端体验与认证系统。
LobeHub 在七月至八月推出 AI 图像生成功能,新增多个服务商支持,并持续优化桌面端体验与认证系统。
## 🌟 重大更新
+1 -1
View File
@@ -9,7 +9,7 @@ tags:
# Gemini Image Generation and Non-Streaming Mode Support 🎨
From August to September, LobeChat added Gemini 2.5 Flash Image generation, introduced non-streaming response mode support, and expanded provider and model support across the ecosystem.
From August to September, LobeHub added Gemini 2.5 Flash Image generation, introduced non-streaming response mode support, and expanded provider and model support across the ecosystem.
## 🌟 Major Updates
+1 -1
View File
@@ -9,7 +9,7 @@ tags:
# Gemini 图像生成与非流式模式支持 🎨
LobeChat 在八月至九月新增 Gemini 2.5 Flash Image 图像生成能力,支持非流式响应模式,并扩展多个 AI 服务商与模型支持。
LobeHub 在八月至九月新增 Gemini 2.5 Flash Image 图像生成能力,支持非流式响应模式,并扩展多个 AI 服务商与模型支持。
## 🌟 重大更新
+1 -1
View File
@@ -9,7 +9,7 @@ tags:
# Claude Sonnet 4.5 and Built-in Python Plugin 🐍
From September to October, LobeChat added support for Claude Sonnet 4.5, introduced a built-in Python plugin, and improved chat list navigation and rich text editing.
From September to October, LobeHub added support for Claude Sonnet 4.5, introduced a built-in Python plugin, and improved chat list navigation and rich text editing.
## 🌟 Key Updates
+1 -1
View File
@@ -9,7 +9,7 @@ tags:
# Claude Sonnet 4.5 与内置 Python 插件 🐍
LobeChat 在九月至十月新增 Claude Sonnet 4.5 模型支持,推出内置 Python 插件,并优化聊天列表导航与富文本编辑体验。
LobeHub 在九月至十月新增 Claude Sonnet 4.5 模型支持,推出内置 Python 插件,并优化聊天列表导航与富文本编辑体验。
## 🌟 主要更新
+1 -1
View File
@@ -9,7 +9,7 @@ tags:
# ComfyUI Integration and Knowledge Base Improvements ⭐
From October to November, LobeChat integrated ComfyUI workflows, added support for multiple AI providers and models, and continued to improve the knowledge base and overall user experience.
From October to November, LobeHub integrated ComfyUI workflows, added support for multiple AI providers and models, and continued to improve the knowledge base and overall user experience.
## 🌟 Key Updates
+1 -1
View File
@@ -9,7 +9,7 @@ tags:
# ComfyUI 集成与知识库优化 ⭐
LobeChat 在十月至十一月集成 ComfyUI 工作流,新增多个 AI 服务商与模型支持,并持续优化知识库与用户体验。
LobeHub 在十月至十一月集成 ComfyUI 工作流,新增多个 AI 服务商与模型支持,并持续优化知识库与用户体验。
## 🌟 重要更新
+1 -1
View File
@@ -10,7 +10,7 @@ tags:
# MCP Cloud Endpoints and Model Library Expansion 🔌
In November, LobeChat continued to improve model support and user experience by adding multiple AI providers and enhancing knowledge base capabilities.
In November, LobeHub continued to improve model support and user experience by adding multiple AI providers and enhancing knowledge base capabilities.
## 🌟 Key Updates
+1 -1
View File
@@ -10,7 +10,7 @@ tags:
# MCP 云端点与模型库扩展 🔌
LobeChat 在十一月持续优化模型支持与用户体验,新增多个 AI 服务商,并改进知识库功能。
LobeHub 在十一月持续优化模型支持与用户体验,新增多个 AI 服务商,并改进知识库功能。
## 🌟 重要更新
@@ -12,7 +12,7 @@ tags:
LobeHub 使用 [Auth.js v5](https://authjs.dev/) 作为外部身份验证服务。Auth.js 是一个开源的身份验证库,它提供了一种简单的方式来实现身份验证和授权功能。本文档将介绍如何使用 Auth.js 来实现新的身份验证方式。
LobeChat 使用 [Better Auth](https://www.better-auth.com) 作为身份验证服务。本文档介绍如何添加新的 SSO 身份验证提供商。
LobeHub 使用 [Better Auth](https://www.better-auth.com) 作为身份验证服务。本文档介绍如何添加新的 SSO 身份验证提供商。
为了在 LobeHub 中添加新的身份验证提供者(例如添加 Okta),你需要完成以下步骤:
@@ -11,7 +11,7 @@ tags:
# Adding New Image Models
> Learn more about the AI image generation modal design in the [AI Image Generation Modal Design Discussion](https://github.com/lobehub/lobe-chat/discussions/7442)
> Learn more about the AI image generation modal design in the [AI Image Generation Modal Design Discussion](https://github.com/lobehub/lobehub/discussions/7442)
## Parameter Standardization
@@ -65,7 +65,7 @@ For image generation models that are not compatible with OpenAI format, you need
### Method 1: Using OpenAI Compatible Factory
Most Providers use `openaiCompatibleFactory` for OpenAI compatibility. You can pass in a custom `createImage` function (reference [PR #8534](https://github.com/lobehub/lobe-chat/pull/8534)).
Most Providers use `openaiCompatibleFactory` for OpenAI compatibility. You can pass in a custom `createImage` function (reference [PR #8534](https://github.com/lobehub/lobehub/pull/8534)).
**Implementation Steps**:
@@ -124,7 +124,7 @@ export const LobeProviderAI = openaiCompatibleFactory({
### Method 2: Direct Implementation in Provider Class
If your Provider has an independent class implementation, you can directly add the `createImage` method in the class (reference [PR #8503](https://github.com/lobehub/lobe-chat/pull/8503)).
If your Provider has an independent class implementation, you can directly add the `createImage` method in the class (reference [PR #8503](https://github.com/lobehub/lobehub/pull/8503)).
**Implementation Steps**:
@@ -9,7 +9,7 @@ tags:
# 添加新的图像模型
> 了解更多关于 AI 绘画模态的设计,请参考 [AI 绘画模态设计讨论](https://github.com/lobehub/lobe-chat/discussions/7442)
> 了解更多关于 AI 绘画模态的设计,请参考 [AI 绘画模态设计讨论](https://github.com/lobehub/lobehub/discussions/7442)
## 参数标准化
@@ -63,7 +63,7 @@ const zhipuImageModels: AIImageModelCard[] = [
### 方式一:使用 OpenAI Compatible Factory
大部分 Provider 都使用 `openaiCompatibleFactory` 来兼容 OpenAI,可以通过传入自定义的 `createImage` 函数(参考 [PR #8534](https://github.com/lobehub/lobe-chat/pull/8534))。
大部分 Provider 都使用 `openaiCompatibleFactory` 来兼容 OpenAI,可以通过传入自定义的 `createImage` 函数(参考 [PR #8534](https://github.com/lobehub/lobehub/pull/8534))。
**实现步骤**
@@ -122,7 +122,7 @@ export const LobeProviderAI = openaiCompatibleFactory({
### 方式二:在 Provider 类中直接实现
如果你的 Provider 有独立的类实现,可以直接在类中添加 `createImage` 方法(参考 [PR #8503](https://github.com/lobehub/lobe-chat/pull/8503))。
如果你的 Provider 有独立的类实现,可以直接在类中添加 `createImage` 方法(参考 [PR #8503](https://github.com/lobehub/lobehub/pull/8503))。
**实现步骤**
+10 -10
View File
@@ -1,18 +1,18 @@
---
title: Lobe Chat API Client-Server Interaction Logic
title: LobeHub API Client-Server Interaction Logic
description: >-
Explore the client-server interaction logic of Lobe Chat API, including event
Explore the client-server interaction logic of LobeHub API, including event
sequences.
tags:
- Lobe Chat API
- LobeHub API
- Client-Server Interaction
- Event Sequences
- API Logic
---
# Lobe Chat API Client-Server Interaction Logic
# LobeHub API Client-Server Interaction Logic
This document explains the implementation logic of Lobe Chat API in client-server interactions, including event sequences and core components involved.
This document explains the implementation logic of LobeHub API in client-server interactions, including event sequences and core components involved.
## Interaction Sequence Diagram
@@ -201,7 +201,7 @@ sequenceDiagram
## AgentRuntime Overview
AgentRuntime is a core abstraction layer in Lobe Chat that encapsulates a unified interface for interacting with different AI model providers. Its main responsibilities and features include:
AgentRuntime is a core abstraction layer in LobeHub that encapsulates a unified interface for interacting with different AI model providers. Its main responsibilities and features include:
1. **Unified Abstraction Layer**: AgentRuntime provides a unified interface that hides the implementation details and differences between various AI provider APIs (such as OpenAI, Anthropic, Bedrock, etc.).
@@ -244,7 +244,7 @@ AgentRuntime is a core abstraction layer in Lobe Chat that encapsulates a unifie
**Adapter Implementation Examples**:
1. **OpenRouter Adapter**: OpenRouter is a unified API that allows access to AI models from multiple providers. Lobe Chat implements support for OpenRouter through an adapter:
1. **OpenRouter Adapter**: OpenRouter is a unified API that allows access to AI models from multiple providers. LobeHub implements support for OpenRouter through an adapter:
```ts
// OpenRouter adapter implementation
@@ -258,7 +258,7 @@ AgentRuntime is a core abstraction layer in Lobe Chat that encapsulates a unifie
apiKey: options.apiKey,
baseURL: OPENROUTER_BASE_URL,
defaultHeaders: {
'HTTP-Referer': 'https://github.com/lobehub/lobe-chat',
'HTTP-Referer': 'https://github.com/lobehub/lobehub',
'X-Title': 'LobeHub',
},
});
@@ -267,7 +267,7 @@ AgentRuntime is a core abstraction layer in Lobe Chat that encapsulates a unifie
// Implement chat functionality
async chat(payload: ChatCompletionCreateParamsBase, options?: RequestOptions) {
// Convert Lobe Chat request format to OpenRouter format
// Convert LobeHub request format to OpenRouter format
// Handle model mapping, message format, etc.
return this.client.chat.completions.create(
{
@@ -282,7 +282,7 @@ AgentRuntime is a core abstraction layer in Lobe Chat that encapsulates a unifie
}
```
2. **Google Gemini Adapter**: Gemini is Google's large language model. Lobe Chat supports Gemini series models through a dedicated adapter:
2. **Google Gemini Adapter**: Gemini is Google's large language model. LobeHub supports Gemini series models through a dedicated adapter:
```ts
import { GoogleGenerativeAI } from '@google/generative-ai';
+10 -10
View File
@@ -1,16 +1,16 @@
---
title: Lobe Chat API 前后端交互逻辑
description: 深入了解 Lobe Chat API 的前后端交互实现逻辑和核心组件。
title: LobeHub API 前后端交互逻辑
description: 深入了解 LobeHub API 的前后端交互实现逻辑和核心组件。
tags:
- Lobe Chat API
- LobeHub API
- 前后端交互
- 事件序列
- 核心组件
---
# Lobe Chat API 前后端交互逻辑
# LobeHub API 前后端交互逻辑
本文档说明了 Lobe Chat API 在前后端交互中的实现逻辑,包括事件序列和涉及的核心组件。
本文档说明了 LobeHub API 在前后端交互中的实现逻辑,包括事件序列和涉及的核心组件。
## 交互时序图
@@ -199,7 +199,7 @@ sequenceDiagram
## AgentRuntime 说明
AgentRuntime 是 Lobe Chat 中的一个核心抽象层,它封装了与不同 AI 模型提供商交互的统一接口。其主要职责和特点包括:
AgentRuntime 是 LobeHub 中的一个核心抽象层,它封装了与不同 AI 模型提供商交互的统一接口。其主要职责和特点包括:
1. **统一抽象层**AgentRuntime 提供了一个统一的接口,隐藏了不同 AI 提供商 API 的实现细节差异(如 OpenAI、Anthropic、Bedrock 等)。
@@ -242,7 +242,7 @@ AgentRuntime 是 Lobe Chat 中的一个核心抽象层,它封装了与不同 A
**适配器实现示例**
1. **OpenRouter 适配器**OpenRouter 是一个统一 API,可以通过它访问多个模型提供商的 AI 模型。Lobe Chat 通过适配器实现对 OpenRouter 的支持:
1. **OpenRouter 适配器**OpenRouter 是一个统一 API,可以通过它访问多个模型提供商的 AI 模型。LobeHub 通过适配器实现对 OpenRouter 的支持:
```ts
// OpenRouter 适配器实现
@@ -256,7 +256,7 @@ AgentRuntime 是 Lobe Chat 中的一个核心抽象层,它封装了与不同 A
apiKey: options.apiKey,
baseURL: OPENROUTER_BASE_URL,
defaultHeaders: {
'HTTP-Referer': 'https://github.com/lobehub/lobe-chat',
'HTTP-Referer': 'https://github.com/lobehub/lobehub',
'X-Title': 'LobeHub',
},
});
@@ -265,7 +265,7 @@ AgentRuntime 是 Lobe Chat 中的一个核心抽象层,它封装了与不同 A
// 实现聊天功能
async chat(payload: ChatCompletionCreateParamsBase, options?: RequestOptions) {
// 将 Lobe Chat 的请求格式转换为 OpenRouter 格式
// 将 LobeHub 的请求格式转换为 OpenRouter 格式
// 处理模型映射、消息格式等
return this.client.chat.completions.create(
{
@@ -280,7 +280,7 @@ AgentRuntime 是 Lobe Chat 中的一个核心抽象层,它封装了与不同 A
}
```
2. **Google Gemini 适配器**Gemini 是 Google 的大语言模型,Lobe Chat 通过专门的适配器支持 Gemini 系列模型:
2. **Google Gemini 适配器**Gemini 是 Google 的大语言模型,LobeHub 通过专门的适配器支持 Gemini 系列模型:
```ts
import { GoogleGenerativeAI } from '@google/generative-ai';
@@ -13,11 +13,11 @@ tags:
This document aims to guide developers on how to develop a complete feature in LobeHub.
We will use [RFC 021 - Custom Assistant Opening Guidance](https://github.com/lobehub/lobe-chat/discussions/891) as an example to illustrate the complete implementation process.
We will use [RFC 021 - Custom Assistant Opening Guidance](https://github.com/lobehub/lobehub/discussions/891) as an example to illustrate the complete implementation process.
## 1. Update Schema
lobe-chat uses a postgres database, with the browser-side local database using [pglite](https://pglite.dev/) (wasm version of postgres). The project also uses [drizzle](https://orm.drizzle.team/) ORM to operate the database.
lobehub uses a postgres database, with the browser-side local database using [pglite](https://pglite.dev/) (wasm version of postgres). The project also uses [drizzle](https://orm.drizzle.team/) ORM to operate the database.
Compared to the old solution where the browser side used indexDB, having both the browser side and server side use postgres has the advantage that the model layer code can be completely reused.
@@ -160,7 +160,7 @@ Foreseeably, the frontend will add two inputs, calling updateSessionConfig upon
### Data Flow Store Implementation
lobe-chat uses [zustand](https://zustand.docs.pmnd.rs/getting-started/introduction) as the global state management framework. For detailed practices on state management, you can refer to [📘 State Management Best Practices](/docs/development/state-management/state-management-intro).
lobehub uses [zustand](https://zustand.docs.pmnd.rs/getting-started/introduction) as the global state management framework. For detailed practices on state management, you can refer to [📘 State Management Best Practices](/docs/development/state-management/state-management-intro).
There are two stores related to the agent:
@@ -254,7 +254,7 @@ We're adding a new category of settings this time. In `src/features/AgentSetting
- [@ant-design/icons](https://ant.design/components/icon-cn) and [lucide](https://lucide.dev/icons/): icon libraries
- [react-i18next](https://github.com/i18next/react-i18next) and [lobe-i18n](https://github.com/lobehub/lobe-cli-toolbox/tree/master/packages/lobe-i18n): i18n framework and multi-language automatic translation tool
lobe-chat is an internationalized project, so newly added text needs to update the default `locale` file: `src/locales/default/setting.ts`.
lobehub is an internationalized project, so newly added text needs to update the default `locale` file: `src/locales/default/setting.ts`.
Let's take the subcomponent `OpeningQuestion.tsx` as an example. Component implementation:
@@ -12,11 +12,11 @@ tags:
本文档旨在指导开发者了解如何在 LobeHub 中开发一块完整的功能需求。
我们将以 [RFC 021 - 自定义助手开场引导](https://github.com/lobehub/lobe-chat/discussions/891) 为例,阐述完整的实现流程。
我们将以 [RFC 021 - 自定义助手开场引导](https://github.com/lobehub/lobehub/discussions/891) 为例,阐述完整的实现流程。
## 一、更新 schema
lobe-chat 使用 postgres 数据库,浏览器端本地数据库使用 [pglite](https://pglite.dev/)wasm 版本 postgres)。项目还使用了 [drizzle](https://orm.drizzle.team/) ORM 用来操作数据库。
lobehub 使用 postgres 数据库,浏览器端本地数据库使用 [pglite](https://pglite.dev/)wasm 版本 postgres)。项目还使用了 [drizzle](https://orm.drizzle.team/) ORM 用来操作数据库。
相比旧方案浏览器端使用 indexDB 来说,浏览器端和 server 端都使用 postgres 好处在于 model 层代码可以完全复用。
@@ -159,7 +159,7 @@ export const sessionRouter = router({
### 数据流 store 实现
lobe-chat 使用 [zustand](https://zustand.docs.pmnd.rs/getting-started/introduction) 作为全局状态管理框架,对于状态管理的详细实践介绍,可以查阅 [📘 状态管理最佳实践](/zh/docs/development/state-management/state-management-intro)。
lobehub 使用 [zustand](https://zustand.docs.pmnd.rs/getting-started/introduction) 作为全局状态管理框架,对于状态管理的详细实践介绍,可以查阅 [📘 状态管理最佳实践](/zh/docs/development/state-management/state-management-intro)。
和 agent 相关的 store 有两个:
@@ -253,7 +253,7 @@ export const agentSelectors = {
- [@ant-design/icons](https://ant.design/components/icon-cn) 和 [lucide](https://lucide.dev/icons/): 图标库
- [react-i18next](https://github.com/i18next/react-i18next) 和 [lobe-i18n](https://github.com/lobehub/lobe-cli-toolbox/tree/master/packages/lobe-i18n) i18n 框架和多语言自动翻译工具
lobe-chat 是个国际化项目,新加的文案需要更新默认的 `locale` 文件: `src/locales/default/setting.ts` 。
lobehub 是个国际化项目,新加的文案需要更新默认的 `locale` 文件: `src/locales/default/setting.ts` 。
我们以子组件 `OpeningQuestion.tsx` 为例,组件实现:
+23 -14
View File
@@ -17,20 +17,29 @@ The directory structure of LobeHub is as follows:
```bash
src
├── app # Next.js App Router implementation with route groups and API routes
├── components # Reusable UI components
├── config # Application configuration files, including client-side and server-side environment variables
├── features # Function modules related to business functions, such as agent settings, plugin development pop-ups, etc.
├── hooks # Custom utility hooks reused throughout the application
├── layout # Application layout components, such as navigation bars, sidebars, etc.
├── libs # Third-party integrations (analytics, OIDC, etc.)
├── locales # Internationalization language files
├── server # Server-side modules and services
├── services # Encapsulated backend service interfaces, such as HTTP requests
├── store # Zustand store for state management
├── styles # Global styles and CSS-in-JS configurations
├── types # TypeScript type definition files
── utils # Common utility functions
├── app # Next.js App Router implementation with route groups and API routes
├── business # Business logic modules (client and server)
├── components # Reusable UI components
├── config # Application configuration files, including client-side and server-side environment variables
├── const # Application constants and enums
├── envs # Environment variable definitions and validation (analytics, auth, llm, etc.)
├── features # Function modules related to business functions, such as agent settings, plugin development pop-ups, etc.
├── helpers # Utility helpers for tool engineering, placeholder parsing, etc.
├── hooks # Custom utility hooks reused throughout the application
├── layout # Application layout components, such as navigation bars, sidebars, etc.
├── libs # Third-party integrations (analytics, OIDC, etc.)
├── locales # Internationalization language files
├── server # Server-side modules and services
── services # Encapsulated backend service interfaces, such as HTTP requests
├── store # Zustand store for state management
├── styles # Global styles and CSS-in-JS configurations
├── tools # Built-in tools (artifacts, inspectors, interventions, etc.)
├── types # TypeScript type definition files
├── utils # Common utility functions
├── auth.ts # Authentication configuration (Better Auth)
├── instrumentation.ts # Application monitoring and telemetry setup
├── instrumentation.node.ts # Node.js-specific instrumentation
└── proxy.ts # Next.js middleware proxy configuration
```
## app
@@ -15,20 +15,29 @@ LobeHub 的文件夹目录架构如下:
```bash
src
├── app # Next.js App Router 实现,包含路由组和 API 路由
├── components # 可复用的 UI 组件
├── config # 应用的配置文件,包含客户端环境变量与服务端环境变量
├── features # 与业务功能相关的功能模块,如 Agent 设置、插件开发弹窗等
├── hooks # 应用复用自定义的工具 Hooks
├── layout # 应用的布局组件,如导航栏、侧边栏等
├── libs # 第三方集成(分析、OIDC 等)
├── locales # 国际化的语言文件
├── server # 服务端模块和服务
├── services # 封装的后端服务接口,如 HTTP 请求
├── store # 用于状态管理的 zustand store
├── styles # 全局样式和 CSS-in-JS 配置
├── types # TypeScript 的类型定义文件
── utils # 通用的工具函数
├── app # Next.js App Router 实现,包含路由组和 API 路由
├── business # 业务逻辑模块(客户端和服务端)
├── components # 可复用的 UI 组件
├── config # 应用的配置文件,包含客户端环境变量与服务端环境变量
├── const # 应用常量和枚举
├── envs # 环境变量定义和校验(分析、认证、LLM 等)
├── features # 与业务功能相关的功能模块,如 Agent 设置、插件开发弹窗等
├── helpers # 工具辅助函数,用于工具工程、占位符解析等
├── hooks # 全应用复用自定义的工具 Hooks
├── layout # 应用的布局组件,如导航栏、侧边栏等
├── libs # 第三方集成(分析、OIDC 等)
├── locales # 国际化的语言文件
├── server # 服务端模块和服务
── services # 封装的后端服务接口,如 HTTP 请求
├── store # 用于状态管理的 zustand store
├── styles # 全局样式和 CSS-in-JS 配置
├── tools # 内置工具(artifacts、inspectors、interventions 等)
├── types # TypeScript 的类型定义文件
├── utils # 通用的工具函数
├── auth.ts # 认证配置(Better Auth
├── instrumentation.ts # 应用监控和遥测设置
├── instrumentation.node.ts # Node.js 专用的 instrumentation
└── proxy.ts # Next.js 中间件代理配置
```
## app
+4 -4
View File
@@ -39,7 +39,7 @@ First, you need to install the following software:
### VSCode Users
We recommend installing the extensions listed in [.vscode/extensions.json](https://github.com/lobehub/lobe-chat/blob/main/.vscode/extensions.json) for the best development experience.
We recommend installing the extensions listed in [.vscode/extensions.json](https://github.com/lobehub/lobehub/blob/main/.vscode/extensions.json) for the best development experience.
### Project Setup
@@ -48,13 +48,13 @@ After installing the above software, you can start setting up the LobeHub projec
1. **Get the code**: First, you need to clone the LobeHub codebase from GitHub. Run the following command in the terminal:
```bash
git clone https://github.com/lobehub/lobe-chat.git
git clone https://github.com/lobehub/lobehub.git
```
2. **Install dependencies**: Then, navigate to the project directory and use PNPM to install the project's dependencies:
```bash
cd lobe-chat
cd lobehub
pnpm i
```
@@ -82,5 +82,5 @@ Please refer to the [Work with Server-Side Database](/docs/development/basic/wor
During the development process, if you encounter any issues with environment setup or have any questions about LobeHub development, feel free to ask us at any time. We look forward to seeing your contributions!
[codespaces-link]: https://codespaces.new/lobehub/lobe-chat
[codespaces-link]: https://codespaces.new/lobehub/lobehub
[codespaces-shield]: https://github.com/codespaces/badge.svg
@@ -35,7 +35,7 @@ tags:
### VSCode 用户
推荐安装 [.vscode/extensions.json](https://github.com/lobehub/lobe-chat/blob/main/.vscode/extensions.json) 中推荐安装的扩展获得最佳开发体验。
推荐安装 [.vscode/extensions.json](https://github.com/lobehub/lobehub/blob/main/.vscode/extensions.json) 中推荐安装的扩展获得最佳开发体验。
### 项目设置
@@ -44,13 +44,13 @@ tags:
1. **获取代码**:首先,你需要从 GitHub 上克隆 LobeHub 的代码库。在终端中运行以下命令:
```bash
git clone https://github.com/lobehub/lobe-chat.git
git clone https://github.com/lobehub/lobehub.git
```
2. **安装依赖**:然后,进入项目目录,并使用 `pnpm` 安装项目的依赖包:
```bash
cd lobe-chat
cd lobehub
pnpm i
```
@@ -78,5 +78,5 @@ bun run dev
在开发过程中,如果你在环境设置上遇到任何问题,或者有任何关于 LobeHub 开发的问题,欢迎随时向我们提问。我们期待看到你的贡献!
[codespaces-link]: https://codespaces.new/lobehub/lobe-chat
[codespaces-link]: https://codespaces.new/lobehub/lobehub
[codespaces-shield]: https://github.com/codespaces/badge.svg
@@ -101,7 +101,6 @@ S3_ACCESS_KEY_ID=${MINIO_ROOT_USER}
S3_SECRET_ACCESS_KEY=${MINIO_ROOT_PASSWORD}
S3_ENDPOINT=http://localhost:${MINIO_PORT}
S3_BUCKET=${MINIO_LOBE_BUCKET}
S3_PUBLIC_DOMAIN=http://localhost:${MINIO_PORT}
S3_ENABLE_PATH_STYLE=1 # Required for MinIO
S3_SET_ACL=0 # MinIO compatibility
```
@@ -101,7 +101,6 @@ S3_ACCESS_KEY_ID=${MINIO_ROOT_USER}
S3_SECRET_ACCESS_KEY=${MINIO_ROOT_PASSWORD}
S3_ENDPOINT=http://localhost:${MINIO_PORT}
S3_BUCKET=${MINIO_LOBE_BUCKET}
S3_PUBLIC_DOMAIN=http://localhost:${MINIO_PORT}
S3_ENABLE_PATH_STYLE=1 # MinIO 必需
S3_SET_ACL=0 # MinIO 兼容性
```
@@ -54,7 +54,7 @@ This will utilize the `lobe-i18n` tool to process the language files.
Once you have completed the above steps, you need to submit your changes and create a Pull Request.
Ensure that you follow LobeHub's contribution guidelines and provide a necessary description to explain your changes. For example, refer to a similar previous Pull Request [#759](https://github.com/lobehub/lobe-chat/pull/759).
Ensure that you follow LobeHub's contribution guidelines and provide a necessary description to explain your changes. For example, refer to a similar previous Pull Request [#759](https://github.com/lobehub/lobehub/pull/759).
### Additional Information
@@ -54,7 +54,7 @@ npm run i18n
一旦你完成了上述步骤,你需要提交你的更改并创建一个 Pull Request。
请确保你遵循了 LobeHub 的贡献指南,并提供必要的描述来说明你的更改。例如,参考之前的类似 Pull Request [#759](https://github.com/lobehub/lobe-chat/pull/759)。
请确保你遵循了 LobeHub 的贡献指南,并提供必要的描述来说明你的更改。例如,参考之前的类似 Pull Request [#759](https://github.com/lobehub/lobehub/pull/759)。
### 附加信息
@@ -114,11 +114,11 @@ In this example, we demonstrate how to use `i18next` and related plugins to init
We have already supported a variety of languages globally through the following efforts:
- [✨ feat: adding Arabic Language Support #1049](https://github.com/lobehub/lobe-chat/pull/1049)
- [🌐 style: Add Vietnamese files and add the vi-VN option in the General Settings #860](https://github.com/lobehub/lobe-chat/pull/860)
- [🌐 style: support it-IT nl-NL and pl-PL locales #759](https://github.com/lobehub/lobe-chat/pull/759)
- [🌐 feat(locale): Add fr-FR (#637) #645](https://github.com/lobehub/lobe-chat/pull/645)
- [🌐 Add russian localy #137](https://github.com/lobehub/lobe-chat/pull/137)
- [✨ feat: adding Arabic Language Support #1049](https://github.com/lobehub/lobehub/pull/1049)
- [🌐 style: Add Vietnamese files and add the vi-VN option in the General Settings #860](https://github.com/lobehub/lobehub/pull/860)
- [🌐 style: support it-IT nl-NL and pl-PL locales #759](https://github.com/lobehub/lobehub/pull/759)
- [🌐 feat(locale): Add fr-FR (#637) #645](https://github.com/lobehub/lobehub/pull/645)
- [🌐 Add russian localy #137](https://github.com/lobehub/lobehub/pull/137)
To add support for new languages, please refer to the detailed steps in the [New Locale Addition Guide](add-new-locale).
@@ -111,11 +111,11 @@ const createI18nInstance = (lang) => {
我们通过以下工作,已经支持了全球多种语言:
- [✨ feat: adding Arabic Language Support #1049](https://github.com/lobehub/lobe-chat/pull/1049)
- [🌐 style: Add Vietnamese files and add the vi-VN option in the General Settings #860](https://github.com/lobehub/lobe-chat/pull/860)
- [🌐 style: support it-IT nl-NL and pl-PL locales #759](https://github.com/lobehub/lobe-chat/pull/759)
- [🌐 feat(locale): Add fr-FR (#637) #645](https://github.com/lobehub/lobe-chat/pull/645)
- [🌐 Add russian localy #137](https://github.com/lobehub/lobe-chat/pull/137)
- [✨ feat: adding Arabic Language Support #1049](https://github.com/lobehub/lobehub/pull/1049)
- [🌐 style: Add Vietnamese files and add the vi-VN option in the General Settings #860](https://github.com/lobehub/lobehub/pull/860)
- [🌐 style: support it-IT nl-NL and pl-PL locales #759](https://github.com/lobehub/lobehub/pull/759)
- [🌐 feat(locale): Add fr-FR (#637) #645](https://github.com/lobehub/lobehub/pull/645)
- [🌐 Add russian localy #137](https://github.com/lobehub/lobehub/pull/137)
要添加新的语种支持, 详细步骤请参考:[新语种添加指南](/zh/docs/development/internationalization/add-new-locale)。
+8 -8
View File
@@ -29,11 +29,11 @@ tags:
| ![][discover-desktop] | ![][discover-mobile] |
| [⚡️ Lighthouse Report][discover-desktop-report] | [⚡️ Lighthouse Report][discover-mobile-report] |
[chat-desktop]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/chat/desktop/pagespeed.svg
[chat-desktop-report]: https://lobehub.github.io/lobe-chat/lighthouse/chat/desktop/LobeHub_com_chat.html
[chat-mobile]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/chat/mobile/pagespeed.svg
[chat-mobile-report]: https://lobehub.github.io/lobe-chat/lighthouse/chat/mobile/LobeHub_com_chat.html
[discover-desktop]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/discover/desktop/pagespeed.svg
[discover-desktop-report]: https://lobehub.github.io/lobe-chat/lighthouse/discover/desktop/LobeHub_com_discover.html
[discover-mobile]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/discover/mobile/pagespeed.svg
[discover-mobile-report]: https://lobehub.github.io/lobe-chat/lighthouse/discover/mobile/LobeHub_com_discover.html
[chat-desktop]: https://raw.githubusercontent.com/lobehub/lobehub/lighthouse/lighthouse/chat/desktop/pagespeed.svg
[chat-desktop-report]: https://lobehub.github.io/lobehub/lighthouse/chat/desktop/LobeHub_com_chat.html
[chat-mobile]: https://raw.githubusercontent.com/lobehub/lobehub/lighthouse/lighthouse/chat/mobile/pagespeed.svg
[chat-mobile-report]: https://lobehub.github.io/lobehub/lighthouse/chat/mobile/LobeHub_com_chat.html
[discover-desktop]: https://raw.githubusercontent.com/lobehub/lobehub/lighthouse/lighthouse/discover/desktop/pagespeed.svg
[discover-desktop-report]: https://lobehub.github.io/lobehub/lighthouse/discover/desktop/LobeHub_com_discover.html
[discover-mobile]: https://raw.githubusercontent.com/lobehub/lobehub/lighthouse/lighthouse/discover/mobile/pagespeed.svg
[discover-mobile-report]: https://lobehub.github.io/lobehub/lighthouse/discover/mobile/LobeHub_com_discover.html
+8 -8
View File
@@ -30,11 +30,11 @@ tags:
| ![][discover-desktop] | ![][discover-mobile] |
| [⚡️ Lighthouse Report][discover-desktop-report] | [⚡️ Lighthouse Report][discover-mobile-report] |
[chat-desktop]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/chat/desktop/pagespeed.svg
[chat-desktop-report]: https://lobehub.github.io/lobe-chat/lighthouse/chat/desktop/LobeHub_com_chat.html
[chat-mobile]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/chat/mobile/pagespeed.svg
[chat-mobile-report]: https://lobehub.github.io/lobe-chat/lighthouse/chat/mobile/LobeHub_com_chat.html
[discover-desktop]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/discover/desktop/pagespeed.svg
[discover-desktop-report]: https://lobehub.github.io/lobe-chat/lighthouse/discover/desktop/LobeHub_com_discover.html
[discover-mobile]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/discover/mobile/pagespeed.svg
[discover-mobile-report]: https://lobehub.github.io/lobe-chat/lighthouse/discover/mobile/LobeHub_com_discover.html
[chat-desktop]: https://raw.githubusercontent.com/lobehub/lobehub/lighthouse/lighthouse/chat/desktop/pagespeed.svg
[chat-desktop-report]: https://lobehub.github.io/lobehub/lighthouse/chat/desktop/LobeHub_com_chat.html
[chat-mobile]: https://raw.githubusercontent.com/lobehub/lobehub/lighthouse/lighthouse/chat/mobile/pagespeed.svg
[chat-mobile-report]: https://lobehub.github.io/lobehub/lighthouse/chat/mobile/LobeHub_com_chat.html
[discover-desktop]: https://raw.githubusercontent.com/lobehub/lobehub/lighthouse/lighthouse/discover/desktop/pagespeed.svg
[discover-desktop-report]: https://lobehub.github.io/lobehub/lighthouse/discover/desktop/LobeHub_com_discover.html
[discover-mobile]: https://raw.githubusercontent.com/lobehub/lobehub/lighthouse/lighthouse/discover/mobile/pagespeed.svg
[discover-mobile-report]: https://lobehub.github.io/lobehub/lighthouse/discover/mobile/LobeHub_com_discover.html
+22 -15
View File
@@ -34,18 +34,25 @@ The folder directory structure of LobeHub is as follows:
```bash
src
├── app # Code related to the main logic and state management of the application
├── components # Reusable UI components
├── config # Application configuration files, including client and server environment variables
├── const # Used to define constants, such as action types, route names, etc.
├── features # Business-related feature modules, such as Agent settings, plugin development pop-ups, etc.
├── hooks # Custom utility Hooks reusable across the application
├── layout # Application layout components, such as navigation bars, sidebars, etc.
├── locales # Language files for internationalization
├── services # Encapsulated backend service interfaces, such as HTTP requests
├── store # Zustand store for state management
├── types # TypeScript type definition files
── utils # General utility functions
├── app # Next.js App Router implementation with route groups and API routes
├── business # Business logic modules (client and server)
├── components # Reusable UI components
├── config # Application configuration files, including client and server environment variables
├── const # Application constants and enums
├── envs # Environment variable definitions and validation (analytics, auth, llm, etc.)
├── features # Business-related feature modules, such as Agent settings, plugin development pop-ups, etc.
├── helpers # Utility helpers for tool engineering, placeholder parsing, etc.
├── hooks # Custom utility Hooks reusable across the application
├── layout # Application layout components, such as navigation bars, sidebars, etc.
├── libs # Third-party integrations (analytics, OIDC, etc.)
── locales # Language files for internationalization
├── server # Server-side modules and services
├── services # Encapsulated backend service interfaces, such as HTTP requests
├── store # Zustand store for state management
├── styles # Global styles and CSS-in-JS configurations
├── tools # Built-in tools (artifacts, inspectors, interventions, etc.)
├── types # TypeScript type definition files
└── utils # General utility functions
```
For a detailed introduction to the directory structure, see: [Folder Directory Structure](/docs/development/basic/folder-structure)
@@ -59,13 +66,13 @@ We recommend using WebStorm as your integrated development environment (IDE).
1. **Get the code**: Clone the LobeHub code repository locally:
```bash
git clone https://github.com/lobehub/lobe-chat.git
git clone https://github.com/lobehub/lobehub.git
```
2. **Install dependencies**: Enter the project directory and install the required dependencies:
```bash
cd lobe-chat
cd lobehub
# If you use Bun
bun install
# If you use PNPM
@@ -110,6 +117,6 @@ For a detailed guide on internationalization implementation, please refer to [In
To support developers in better understanding and using the technology stack of LobeHub, we provide a comprehensive list of resources and references — [LobeHub Resources and References](/docs/development/basic/resources) - Visit our maintained list of resources, including tutorials, articles, and other useful links.
We encourage developers to utilize these resources to deepen their learning and enhance their skills, join community discussions through [LobeHub GitHub Discussions](https://github.com/lobehub/lobe-chat/discussions) or [Discord](https://discord.com/invite/AYFPHvv2jT), ask questions, or share your experiences.
We encourage developers to utilize these resources to deepen their learning and enhance their skills, join community discussions through [LobeHub GitHub Discussions](https://github.com/lobehub/lobehub/discussions) or [Discord](https://discord.com/invite/AYFPHvv2jT), ask questions, or share your experiences.
If you have any questions or need further assistance, please do not hesitate to contact us through the above channels.
+22 -15
View File
@@ -32,18 +32,25 @@ LobeHub 的文件夹目录架构如下:
```bash
src
├── app # 应用主要逻辑和状态管理相关的代码
├── components # 可复用的 UI 组件
├── config # 应用的配置文件,包含客户端环境变量与服务端环境变量
├── const # 用于定义常量,如 action 类型、路由名等
├── features # 与业务功能相关的功能模块,如 Agent 设置、插件开发弹窗等
├── hooks # 全应用复用自定义的工具 Hooks
├── layout # 应用的布局组件,如导航栏、侧边栏
├── locales # 国际化的语言文件
├── services # 封装的后端服务接口,如 HTTP 请求
├── store # 用于状态管理的 zustand store
├── types # TypeScript 的类型定义文件
── utils # 通用的工具函数
├── app # Next.js App Router 实现,包含路由组和 API 路由
├── business # 业务逻辑模块(客户端和服务端)
├── components # 可复用的 UI 组件
├── config # 应用的配置文件,包含客户端环境变量与服务端环境变量
├── const # 应用常量和枚举
├── envs # 环境变量定义和校验(分析、认证、LLM 等)
├── features # 与业务功能相关的功能模块,如 Agent 设置、插件开发弹窗
├── helpers # 工具辅助函数,用于工具工程、占位符解析等
├── hooks # 全应用复用自定义的工具 Hooks
├── layout # 应用的布局组件,如导航栏、侧边栏等
├── libs # 第三方集成(分析、OIDC 等)
── locales # 国际化的语言文件
├── server # 服务端模块和服务
├── services # 封装的后端服务接口,如 HTTP 请求
├── store # 用于状态管理的 zustand store
├── styles # 全局样式和 CSS-in-JS 配置
├── tools # 内置工具(artifacts、inspectors、interventions 等)
├── types # TypeScript 的类型定义文件
└── utils # 通用的工具函数
```
有关目录架构的详细介绍,详见: [文件夹目录架构](/zh/docs/development/basic/folder-structure)
@@ -57,13 +64,13 @@ src
1. **获取代码**:克隆 LobeHub 的代码库到本地:
```bash
git clone https://github.com/lobehub/lobe-chat.git
git clone https://github.com/lobehub/lobehub.git
```
2. **安装依赖**:进入项目目录,并安装所需依赖:
```bash
cd lobe-chat
cd lobehub
# 如果你使用 Bun
bun install
# 如果你使用 PNPM
@@ -108,6 +115,6 @@ LobeHub 采用 `i18next` 和 `lobe-i18n` 实现多语言支持,确保用户全
为了支持开发者更好地理解和使用 LobeHub 的技术栈,我们提供了一份详尽的资源与参考列表 —— [LobeHub 资源与参考](/zh/docs/development/basic/resources) - 访问我们维护的资源列表,包括教程、文章和其他有用的链接。
我们鼓励开发者利用这些资源深入学习和提升技能,通过 [LobeHub GitHub Discussions](https://github.com/lobehub/lobe-chat/discussions) 或者 [Discord](https://discord.com/invite/AYFPHvv2jT) 加入社区讨论,提出问题或分享你的经验。
我们鼓励开发者利用这些资源深入学习和提升技能,通过 [LobeHub GitHub Discussions](https://github.com/lobehub/lobehub/discussions) 或者 [Discord](https://discord.com/invite/AYFPHvv2jT) 加入社区讨论,提出问题或分享你的经验。
如果你有任何疑问,或者需要进一步的帮助,请不要犹豫,请通过上述渠道与我们联系。
@@ -1,87 +0,0 @@
---
title: Configuring Casdoor Authentication for LobeChat
description: >-
Learn how to configure Casdoor SSO for LobeChat, including creating an
application and setting up environment variables.
tags:
- Casdoor
- Authentication
- LobeChat
- Single Sign-On
- OIDC
---
# Configuring Casdoor Authentication
[Casdoor](https://casdoor.org/) is an open-source Identity Access Management (IAM) platform with web UI for SSO.
<Steps>
### Create Application in Casdoor
1. Log in to your Casdoor admin console
2. Go to **Applications** and click **Add**
3. Configure the application:
- Name: `LobeChat`
- Organization: Select your organization
- Redirect URLs: Add your callback URL
<Callout type={'info'}>
**Callback URL Format**: `https://your-domain.com/api/auth/callback/casdoor`
</Callout>
4. Save and note down the **Client ID** and **Client Secret**
### Get Issuer URL
The issuer URL is your Casdoor server URL, typically: `https://your-casdoor-domain`
### Configure Environment Variables
When deploying LobeChat, you need to configure the following environment variables:
| Environment Variable | Type | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------- |
| `AUTH_SECRET` | Required | Key used to encrypt session tokens. Generate using: `openssl rand -base64 32` |
| `AUTH_SSO_PROVIDERS` | Required | SSO provider for LobeChat. Use `casdoor` for Casdoor |
| `AUTH_CASDOOR_ID` | Required | Client ID from Casdoor application |
| `AUTH_CASDOOR_SECRET` | Required | Client Secret from Casdoor application |
| `AUTH_CASDOOR_ISSUER` | Required | Casdoor server URL (e.g., `https://your-casdoor-domain`) |
| `CASDOOR_WEBHOOK_SECRET` | Optional | Secret key for validating Webhook requests from Casdoor |
<Callout type={'tip'}>
Go to [📘 Environment Variables](/docs/self-hosting/environment-variables/auth#casdoor) for detailed information on these variables.
</Callout>
### Configure Webhook (Optional)
> Available in Casdoor `>=1.843.0`.
Configure Casdoor [Webhook](https://www.casdoor.org/docs/webhooks/overview#setting-up-a-webhook) to sync user data updates to LobeChat.
**Synced data fields**:
- Avatar (`avatar`)
- Email (`email`)
- Display name (`displayName`)
**Configuration steps**:
1. Go to **Admin Tools** -> **Webhooks** and create a Webhook
2. Fill in the following fields:
- URL: `https://your-domain.com/api/webhooks/casdoor`
- Method: `POST`
- Content Type: `application/json`
- Headers: `casdoor-secret`: `your-webhook-secret`
- Events: `update-user`
3. Generate a secret at [generate-secret.vercel.app/10](https://generate-secret.vercel.app/10)
4. Set the secret in the `CASDOOR_WEBHOOK_SECRET` environment variable
</Steps>
<Callout type={'info'}>
After successful deployment, users will be able to authenticate with Casdoor and use LobeChat.
</Callout>
## Related Resources
- [Casdoor Documentation](https://casdoor.org/docs/overview)
- [Casdoor Application Configuration](https://casdoor.org/docs/application/config)
@@ -1,83 +0,0 @@
---
title: 在 LobeChat 中配置 Casdoor 身份验证
description: 学习如何在 LobeChat 中配置 Casdoor SSO,包括创建应用和设置环境变量。
tags:
- Casdoor
- 身份验证
- LobeChat
- 单点登录
- OIDC
---
# 配置 Casdoor 身份验证
[Casdoor](https://casdoor.org/) 是一个开源的身份访问管理 (IAM) 平台,提供 Web UI 支持单点登录。
<Steps>
### 在 Casdoor 中创建应用
1. 登录 Casdoor 管理控制台
2. 前往 **Applications**,点击 **Add**
3. 配置应用:
- Name: `LobeChat`
- Organization: 选择你的组织
- Redirect URLs: 添加回调 URL
<Callout type={'info'}>
**回调 URL 格式**: `https://your-domain.com/api/auth/callback/casdoor`
</Callout>
4. 保存并记下 **Client ID** 和 **Client Secret**
### 获取 Issuer URL
Issuer URL 是 Casdoor 服务器 URL,通常为:`https://your-casdoor-domain`
### 配置环境变量
在部署 LobeChat 时,你需要配置以下环境变量:
| 环境变量 | 类型 | 描述 |
| ------------------------ | -- | ------------------------------------------------- |
| `AUTH_SECRET` | 必选 | 用于加密会话令牌的密钥。使用以下命令生成:`openssl rand -base64 32` |
| `AUTH_SSO_PROVIDERS` | 必选 | SSO 提供商。使用 Casdoor 请填写 `casdoor` |
| `AUTH_CASDOOR_ID` | 必选 | Casdoor 应用的 Client ID |
| `AUTH_CASDOOR_SECRET` | 必选 | Casdoor 应用的 Client Secret |
| `AUTH_CASDOOR_ISSUER` | 必选 | Casdoor 服务器 URL(例如 `https://your-casdoor-domain` |
| `CASDOOR_WEBHOOK_SECRET` | 可选 | 用于验证 Casdoor 发送的 Webhook 请求是否合法的密钥 |
<Callout type={'tip'}>
前往 [📘 环境变量](/zh/docs/self-hosting/environment-variables/auth#casdoor) 可查阅相关变量详情。
</Callout>
### 配置 Webhook(可选)
> 在 Casdoor `>=1.843.0` 上可用。
配置 Casdoor 的 [Webhook](https://www.casdoor.org/docs/webhooks/overview#setting-up-a-webhook) 以便在用户信息更新时同步到 LobeChat。
**同步的数据字段**
- 头像 (`avatar`)
- 邮箱 (`email`)
- 显示名称 (`displayName`)
**配置步骤**
1. 前往 `管理工具` -> `Webhooks`,创建一个 Webhook
2. 填写以下字段:
- 链接:`https://your-domain.com/api/webhooks/casdoor`
- 方法:`POST`
- 内容类型:`application/json`
- 协议头:`casdoor-secret`: `你的Webhook密钥`
- 事件:`update-user`
3. 密钥可前往 [generate-secret.vercel.app/10](https://generate-secret.vercel.app/10) 生成
4. 将密钥填写到环境变量 `CASDOOR_WEBHOOK_SECRET`
</Steps>
<Callout type={'info'}>部署成功后,用户将可以通过 Casdoor 身份认证并使用 LobeChat。</Callout>
## 相关资源
- [Casdoor 文档](https://casdoor.org/docs/overview)
- [Casdoor 应用配置](https://casdoor.org/docs/application/config)
+1 -1
View File
@@ -57,4 +57,4 @@ You can achieve various feature combinations using the above configuration synta
| `commercial_hide_github` | Hides GitHub-related links in settings footer (requires commercial license). | Disabled |
| `commercial_hide_docs` | Hides documentation and help menu including changelog, docs, and feedback (requires commercial license). | Disabled |
You can always check the [featureFlags](https://github.com/lobehub/lobe-chat/blob/main/src/config/featureFlags/schema.ts) to get the latest list of feature flags.
You can always check the [featureFlags](https://github.com/lobehub/lobehub/blob/main/src/config/featureFlags/schema.ts) to get the latest list of feature flags.
@@ -53,4 +53,4 @@ tags:
| `commercial_hide_github` | 隐藏设置页面底部的 GitHub 相关链接(需要商业授权)。 | 关闭 |
| `commercial_hide_docs` | 隐藏文档和帮助菜单,包括更新日志、文档和反馈(需要商业授权)。 | 关闭 |
你可以随时检查 [featureFlags](https://github.com/lobehub/lobe-chat/blob/main/src/config/featureFlags/schema.ts) 以获取最新的特性标志列表。
你可以随时检查 [featureFlags](https://github.com/lobehub/lobehub/blob/main/src/config/featureFlags/schema.ts) 以获取最新的特性标志列表。
@@ -22,12 +22,12 @@ LobeHub supports file upload and knowledge base management. This feature relies
PostgreSQL is a powerful open-source relational database system, and PGVector is its extension for vector operations.
- **Purpose**: Store structured data and vector indexes
- **Deployment Tip**: Use official Docker image for quick deployment
- **Deployment Tip**: Use the ParadeDB Docker image for quick deployment with pgvector and pg\_search plugins
Deployment script example:
```
docker run -p 5432:5432 -d --name pg -e POSTGRES_PASSWORD=mysecretpassword pgvector/pgvector:pg17
docker run -p 5432:5432 -d --name pg -e POSTGRES_PASSWORD=mysecretpassword paradedb/paradedb:latest-pg17
```
- **Note**: Ensure sufficient resources for vector operations
@@ -20,12 +20,12 @@ LobeHub 支持文件上传 / 知识库管理。该功能依赖于以下核心技
PostgreSQL 是一个强大的开源关系型数据库系统,而 PGVector 是其扩展,为向量操作提供支持。
- **用途**:存储结构化数据和向量索引
- **部署建议**:使用官方 Docker 镜像可以快速部署 PostgreSQL 和 PGVector
- **部署建议**:使用 ParadeDB Docker 镜像可以快速部署包含 pgvector 和 pg\_search 插件的 PostgreSQL
示例部署脚本:
```
docker run -p 5432:5432 -d --name pg -e POSTGRES_PASSWORD=mysecretpassword pgvector/pgvector:pg17
docker run -p 5432:5432 -d --name pg -e POSTGRES_PASSWORD=mysecretpassword paradedb/paradedb:latest-pg17
```
- **注意事项**:确保分配足够的资源以处理向量操作
+1 -1
View File
@@ -191,7 +191,7 @@ This URL should point to a functional SearXNG instance. You can choose to self-h
You can find publicly available SearXNG instances in the [SearXNG instance list](https://searx.space/). Choose an instance that is fast and reliable, and then configure its URL in LobeHub.
> Note that the `searxng` you use must have `json` output enabled; otherwise, the `lobe-chat` call will result in an error. If self-hosting, find the `searxng` configuration file and add `json` as shown below.
> Note that the `searxng` you use must have `json` output enabled; otherwise, the `lobehub` call will result in an error. If self-hosting, find the `searxng` configuration file and add `json` as shown below.
```bash
$ vi searxng/settings.yml
@@ -186,7 +186,7 @@ SEARXNG_URL=https://searxng-instance.com
您可以在 [SearXNG 实例列表](https://searx.space/) 中找到公开可用的 SearXNG 实例。选择一个响应速度快、可靠性高的实例,然后将其 URL 配置到 LobeHub 中。
> 注意,使用的 `searxng` 必须开启 `json` 输出,否则 `lobe-chat` 调用会报错。如果是自托管,类似下面这样,找到 `searxng` 的配置文件,追加 `json` 即可。
> 注意,使用的 `searxng` 必须开启 `json` 输出,否则 `lobehub` 调用会报错。如果是自托管,类似下面这样,找到 `searxng` 的配置文件,追加 `json` 即可。
```bash
$ vi searxng/settings.yml
+6 -6
View File
@@ -1,6 +1,6 @@
---
title: Configure Redis Cache Service
description: Learn how to configure Redis cache service to optimize LobeChat performance and session management.
description: Learn how to configure Redis cache service to optimize LobeHub performance and session management.
tags:
- Redis
- Cache
@@ -10,17 +10,17 @@ tags:
# Configure Redis Cache Service
LobeChat uses Redis as a high-performance cache and session storage service to optimize system performance and manage user authentication state.
LobeHub uses Redis as a high-performance cache and session storage service to optimize system performance and manage user authentication state.
<Callout type={'info'}>
LobeChat uses the standard Redis protocol (via ioredis library), supporting any Redis
LobeHub uses the standard Redis protocol (via ioredis library), supporting any Redis
protocol-compatible service, including official Redis, self-hosted Redis, and cloud provider Redis
services (such as AWS ElastiCache, Alibaba Cloud Redis, etc.).
</Callout>
## Use Cases
Redis is used in LobeChat for the following scenarios:
Redis is used in LobeHub for the following scenarios:
### Authentication Session Storage
@@ -57,7 +57,7 @@ Caches Agent configuration data to reduce database queries and improve response
### `REDIS_PREFIX`
The prefix for Redis keys, used to isolate LobeChat data in a shared Redis instance.
The prefix for Redis keys, used to isolate LobeHub data in a shared Redis instance.
- Default: `lobechat`
- Example: `REDIS_PREFIX=my-lobechat`
@@ -119,7 +119,7 @@ REDIS_PREFIX=lobechat
## Notes
<Callout type={'warning'}>
Redis is an optional service. If `REDIS_URL` is not configured, LobeChat will still function
Redis is an optional service. If `REDIS_URL` is not configured, LobeHub will still function
normally, but will lose the caching and session management optimizations mentioned above.
</Callout>
+6 -6
View File
@@ -1,6 +1,6 @@
---
title: 配置 Redis 缓存服务
description: 了解如何配置 Redis 缓存服务以优化 LobeChat 的性能和会话管理。
description: 了解如何配置 Redis 缓存服务以优化 LobeHub 的性能和会话管理。
tags:
- Redis
- 缓存
@@ -10,17 +10,17 @@ tags:
# 配置 Redis 缓存服务
LobeChat 使用 Redis 作为高性能缓存和会话存储服务,用于优化系统性能和管理用户认证状态。
LobeHub 使用 Redis 作为高性能缓存和会话存储服务,用于优化系统性能和管理用户认证状态。
<Callout type={'info'}>
LobeChat 使用标准 Redis 协议(通过 ioredis 库),支持任何兼容 Redis 协议的服务,包括 Redis
LobeHub 使用标准 Redis 协议(通过 ioredis 库),支持任何兼容 Redis 协议的服务,包括 Redis
官方服务、自部署 Redis、以及云服务商提供的 Redis 服务(如 AWS ElastiCache、阿里云 Redis
等)。
</Callout>
## 使用场景
Redis 在 LobeChat 中主要用于以下场景:
Redis 在 LobeHub 中主要用于以下场景:
### 认证会话存储
@@ -57,7 +57,7 @@ Redis 在 LobeChat 中主要用于以下场景:
### `REDIS_PREFIX`
Redis 键的前缀,用于在共享 Redis 实例中隔离 LobeChat 的数据。
Redis 键的前缀,用于在共享 Redis 实例中隔离 LobeHub 的数据。
- 默认值:`lobechat`
- 示例:`REDIS_PREFIX=my-lobechat`
@@ -118,7 +118,7 @@ REDIS_PREFIX=lobechat
## 注意事项
<Callout type={'warning'}>
Redis 是可选服务。如果不配置 `REDIS_URL`LobeChat 仍然可以正常运行,但会失去上述缓存和会话管理的优化功能。
Redis 是可选服务。如果不配置 `REDIS_URL`LobeHub 仍然可以正常运行,但会失去上述缓存和会话管理的优化功能。
</Callout>
- **内存管理**:Redis 是内存数据库,请确保服务器有足够的内存
+3 -3
View File
@@ -1,6 +1,6 @@
---
title: Configuring Upstash Redis Service
description: Step-by-step guide to configure Upstash Redis for LobeChat cache and session storage.
description: Step-by-step guide to configure Upstash Redis for LobeHub cache and session storage.
tags:
- Upstash
- Redis
@@ -10,7 +10,7 @@ tags:
# Configuring Upstash Redis Service
[Upstash](https://upstash.com/) is a serverless Redis service that provides a free tier and pay-as-you-go pricing, making it ideal for LobeChat deployments.
[Upstash](https://upstash.com/) is a serverless Redis service that provides a free tier and pay-as-you-go pricing, making it ideal for LobeHub deployments.
## Configuration Steps
@@ -37,7 +37,7 @@ tags:
```
<Callout type={'info'}>
Upstash uses `rediss://` (with double 's') for TLS connections. LobeChat supports this format automatically.
Upstash uses `rediss://` (with double 's') for TLS connections. LobeHub supports this format automatically.
</Callout>
</Steps>
@@ -1,6 +1,6 @@
---
title: 配置 Upstash Redis 服务
description: 详细指南:如何配置 Upstash Redis 用于 LobeChat 的缓存和会话存储。
description: 详细指南:如何配置 Upstash Redis 用于 LobeHub 的缓存和会话存储。
tags:
- Upstash
- Redis
@@ -10,7 +10,7 @@ tags:
# 配置 Upstash Redis 服务
[Upstash](https://upstash.com/) 是一个 Serverless Redis 服务,提供免费额度和按量付费模式,非常适合 LobeChat 部署使用。
[Upstash](https://upstash.com/) 是一个 Serverless Redis 服务,提供免费额度和按量付费模式,非常适合 LobeHub 部署使用。
## 配置步骤
@@ -37,7 +37,7 @@ tags:
```
<Callout type={'info'}>
Upstash 使用 `rediss://`(双 's')表示 TLS 连接,LobeChat 自动支持此格式。
Upstash 使用 `rediss://`(双's')表示 TLS 连接,LobeHub 自动支持此格式。
</Callout>
</Steps>
-9
View File
@@ -50,15 +50,6 @@ The best practice in this area is to use a file storage service (S3) to store im
Whether to set the ACL to `public-read` when uploading files. This option is enabled by default. If the service provider does not support setting individual ACLs for files (i.e., all files inherit the ACL of the storage bucket), enabling this option may cause request errors. Set `S3_SET_ACL` to `0` to disable it.
### `S3_PUBLIC_DOMAIN`
The public access domain of the storage bucket, used to access files in the storage bucket. This address needs to be **publicly readable**. The reason is that when OpenAI's gpt-4o and other vision models recognize images, OpenAI will try to download this image link on their servers. Therefore, this link must be publicly accessible. If it is a private link, OpenAI will not be able to access the image and thus will not be able to recognize the image content properly.
<Callout type={'warning'}>
Additionally, since this access domain is often a separate URL, it needs to be configured to allow
cross-origin access to the site. Otherwise, cross-origin issues will occur in the browser.
</Callout>
### `S3_ENABLE_PATH_STYLE`
Whether to enable the `path-style` access mode of S3. This option is disabled by default. If your S3 service provider uses `path-style`, set `S3_ENABLE_PATH_STYLE` to `1` to enable it.
-8
View File
@@ -46,14 +46,6 @@ LobeHub 在 [很早以前](https://x.com/lobehub/status/1724289575672291782) 就
是否在上传文件时设置 ACL 为 `public-read`。该选项默认启用。如果服务商不支持为文件设置单独的 ACL(即所有文件继承存储桶的 ACL),启用此选项可能会导致请求错误,将 `S3_SET_ACL` 设置为 `0` 即可关闭。
### `S3_PUBLIC_DOMAIN`
存储桶对外的访问域名,用于访问存储桶中的文件,这个地址需要**允许互联网可读**。 原因是 OpenAI 的 gpt-4o 等视觉模型识别图片时,OpenAI 会尝试在他们的服务器中下载这个图片链接,因此这个链接必须是公开可访问的,如果是私有的链接,OpenAI 将无法访问到这个图片,进而无法正常识别到图片内容。
<Callout type={'warning'}>
此外,由于该访问域名往往是一个独立的网址,因此需要配置允许站点的跨域访问,否则会在浏览器中出现跨域问题。
</Callout>
### `S3_ENABLE_PATH_STYLE`
是否启用 S3 的 `path-style` 访问模式。此选项默认禁用。如果您的 S3 服务提供商使用 `path-style`,请将 `S3_ENABLE_PATH_STYLE` 设置为 `1` 以启用它。
@@ -39,8 +39,6 @@ We need to configure an S3 storage service in the server-side database to store
S3_BUCKET=LobeHub
# Request endpoint of the bucket (note that the path in this link includes the bucket name, which must be removed, or use the link provided on the page for applying S3 API token)
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
# Access domain of the bucket
S3_PUBLIC_DOMAIN=https://s3-for-LobeHub.your-domain.com
```
<Callout type={'warning'}>
@@ -118,9 +116,6 @@ S3_SECRET_ACCESS_KEY=55af75d8eb6b99f189f6a35f855336ea62cd9c4751a5cf4337c53c1d3f4
S3_BUCKET=LobeHub
# Bucket Request Endpoint
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
# Public Access Domain for the Bucket
S3_PUBLIC_DOMAIN=https://s3-dev.your-domain.com
# Bucket Region, such as us-west-1. Generally not required, but some service providers may need it.
# S3_REGION=us-west-1
```
@@ -40,8 +40,6 @@ tags:
S3_BUCKET=LobeHub
# 存储桶的请求端点(注意此处链接的路径带存储桶名称,必须删除该路径,或使用申请 S3 API token 页面所提供的链接)
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
# 存储桶对外的访问域名
S3_PUBLIC_DOMAIN=https://s3-for-LobeHub.your-domain.com
```
<Callout type={'warning'}>`S3_ENDPOINT`必须删除其路径,否则会无法访问所上传文件</Callout>
@@ -115,9 +113,6 @@ S3_SECRET_ACCESS_KEY=55af75d8eb6b99f189f6a35f855336ea62cd9c4751a5cf4337c53c1d3f4
S3_BUCKET=LobeHub
# 存储桶的请求端点
S3_ENDPOINT=https://0b33a03b5c993fd2f453379dc36558e5.r2.cloudflarestorage.com
# 存储桶对外的访问域名
S3_PUBLIC_DOMAIN=https://s3-dev.your-domain.com
# 桶的区域,如 us-west-1,一般来说不需要添加,但某些服务商则需要配置
# S3_REGION=us-west-1
```
+91 -93
View File
@@ -12,131 +12,129 @@ tags:
We need to configure an S3-compatible storage service in the server-side database to store files.
<Callout type={'info'}>
Due to recent changes in MinIO's commercial strategy, we no longer recommend MinIO as the S3 storage backend. Please migrate to open-source solutions such as [RustFS](https://rustfs.com/) or [ceph](https://ceph.io/), or to cloud providers like Tencent Cloud Object Storage or Cloudflare R2.
Due to recent changes in MinIO's commercial strategy, we no longer recommend MinIO as the S3 storage backend. Please migrate to open-source solutions such as [RustFS](https://rustfs.com/) or [ceph](https://ceph.io/), or to cloud providers like Tencent Cloud Object Storage or Cloudflare R2.
</Callout>
## Configuration Steps
<Steps>
### Deploy RustFS
### Deploy RustFS
First, pull the RustFS Docker image:
First, pull the RustFS Docker image:
```shell
docker pull rustfs/rustfs:latest
```
```shell
docker pull rustfs/rustfs:latest
```
You can inspect its version with the following command. We recommend version v1.0.0 or above:
You can inspect its version with the following command. We recommend version v1.0.0 or above:
```shell
docker inspect --format='{{index .Config.Labels "version"}}' rustfs/rustfs:latest
```
```shell
docker inspect --format='{{index .Config.Labels "version"}}' rustfs/rustfs:latest
```
We recommend using Docker Compose to deploy RustFS:
We recommend using Docker Compose to deploy RustFS:
```yml
services:
rustfs:
image: rustfs/rustfs:latest
container_name: lobe-rustfs
ports:
- '9000:9000'
- '9001:9001'
environment:
- RUSTFS_CONSOLE_ENABLE=true
- RUSTFS_ACCESS_KEY=<YOUR_ACCESS_KEY>
- RUSTFS_SECRET_KEY=<YOUR_SECRET_KEY>
volumes:
- rustfs-data:/data
```yml
services:
rustfs:
image: rustfs/rustfs:latest
container_name: lobe-rustfs
ports:
- '9000:9000'
- '9001:9001'
environment:
- RUSTFS_CONSOLE_ENABLE=true
- RUSTFS_ACCESS_KEY=<YOUR_ACCESS_KEY>
- RUSTFS_SECRET_KEY=<YOUR_SECRET_KEY>
volumes:
- rustfs-data:/data
volumes:
rustfs-data:
```
volumes:
rustfs-data:
```
Then start RustFS:
Then start RustFS:
```shell
docker compose up -d
```
```shell
docker compose up -d
```
### Create a Bucket
### Create a Bucket
Open the RustFS WebUI (`http://localhost:9001/`) and you will be redirected to the login screen. Enter the username (`RUSTFS_ACCESS_KEY` in the `docker-compose.yml`) and password (`RUSTFS_SECRET_KEY` in the same file) to sign in.
Open the RustFS WebUI (`http://localhost:9001/`) and you will be redirected to the login screen. Enter the username (`RUSTFS_ACCESS_KEY` in the `docker-compose.yml`) and password (`RUSTFS_SECRET_KEY` in the same file) to sign in.
Click `Object Storage` in the left sidebar, then the `Create Bucket` button in the top-right corner to create a new bucket. This example uses the name `lobe`. Leave Versioning and Object Lock disabled (default settings).
Click `Object Storage` in the left sidebar, then the `Create Bucket` button in the top-right corner to create a new bucket. This example uses the name `lobe`. Leave Versioning and Object Lock disabled (default settings).
<Image alt={"Create Bucket"} src={'https://github.com/user-attachments/assets/27c37617-a813-4de5-b0bf-c7167999c856'} />
<Image alt={"Create Bucket"} src={'https://github.com/user-attachments/assets/27c37617-a813-4de5-b0bf-c7167999c856'} />
Go to the bucket and click `Settings`, choose `Custom` for the policy, and paste the following JSON to make the bucket public-read/private-write:
Go to the bucket and click `Settings`, choose `Custom` for the policy, and paste the following JSON to make the bucket public-read/private-write:
```json
{
"ID": "",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": [
"*"
]
},
"Action": [
"s3:GetObject"
],
"NotAction": [],
"Resource": [
"arn:aws:s3:::lobe/*"
],
"NotResource": [],
"Condition": {}
}
]
}
```
```json
{
"ID": "",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": [
"*"
]
},
"Action": [
"s3:GetObject"
],
"NotAction": [],
"Resource": [
"arn:aws:s3:::lobe/*"
],
"NotResource": [],
"Condition": {}
}
]
}
```
Save the settings to apply the policy.
Save the settings to apply the policy.
### Configure Access Keys
### Configure Access Keys
<Callout type={'warning'}>
You can reuse the `RUSTFS_ACCESS_KEY` and `RUSTFS_SECRET_KEY` defined in the `docker-compose.yml`, but for better security we recommend creating a dedicated access key.
</Callout>
<Callout type={'warning'}>
You can reuse the `RUSTFS_ACCESS_KEY` and `RUSTFS_SECRET_KEY` defined in the `docker-compose.yml`, but for better security we recommend creating a dedicated access key.
</Callout>
Click `Access Key` in the left sidebar, then `Add Access Key` to create a new key. The name is arbitrary, and you can keep the default main-account policy.
Click `Access Key` in the left sidebar, then `Add Access Key` to create a new key. The name is arbitrary, and you can keep the default main-account policy.
Copy the generated Access Key and Secret Key (the `Export` button lets you save the JSON locally). The English labels in the UI are confusing, but remember the shorter string is the Access Key and the longer string is the Secret Key (the exported JSON is correct).
Copy the generated Access Key and Secret Key (the `Export` button lets you save the JSON locally). The English labels in the UI are confusing, but remember the shorter string is the Access Key and the longer string is the Secret Key (the exported JSON is correct).
<Image alt={"Add Key"} src={'https://github.com/user-attachments/assets/81f18b20-3918-4f77-8571-07d0c4a79aec'} />
<Image alt={"Add Key"} src={'https://github.com/user-attachments/assets/81f18b20-3918-4f77-8571-07d0c4a79aec'} />
<Image alt={"Export Key"} src={'https://github.com/user-attachments/assets/4dde41ec-985b-4781-8c77-aac65555a32f'} />
<Image alt={"Export Key"} src={'https://github.com/user-attachments/assets/4dde41ec-985b-4781-8c77-aac65555a32f'} />
### Configure Reverse Proxy
### Configure Reverse Proxy
You also need reverse-proxy rules so that RustFS is accessible from the LAN/public internet. Map the following ports to domains:
You also need reverse-proxy rules so that RustFS is accessible from the LAN/public internet. Map the following ports to domains:
| Domain | Port | Required |
| ---------------------------- | ------ | -------- |
| `lobe-s3-api.example.com` | `9000` | Yes |
| `lobe-s3-ui.example.com` | `9001` | |
| Domain | Port | Required |
| ------------------------- | ------ | -------- |
| `lobe-s3-api.example.com` | `9000` | Yes |
| `lobe-s3-ui.example.com` | `9001` | |
After completing the reverse proxy, remember to configure the corresponding SSL certificate and enable HTTPS access.
After completing the reverse proxy, remember to configure the corresponding SSL certificate and enable HTTPS access.
### Set Environment Variables
### Set Environment Variables
Update the LobeChat `.env` file with the following environment variables to use RustFS as the S3 backend:
Update the LobeHub `.env` file with the following environment variables to use RustFS as the S3 backend:
```shell
# RustFS Access Key / Secret Key
S3_ACCESS_KEY_ID=<YOUR_ACCESS_KEY>
S3_SECRET_ACCESS_KEY=<YOUR_SECRET_KEY>
# RustFS API endpoint
S3_ENDPOINT=https://lobe-s3-api.example.com
# Bucket name
S3_BUCKET=lobe
# Public domain for accessing the bucket
S3_PUBLIC_DOMAIN=https://lobe-s3-api.example.com
S3_ENABLE_PATH_STYLE=1
```
```shell
# RustFS Access Key / Secret Key
S3_ACCESS_KEY_ID=<YOUR_ACCESS_KEY>
S3_SECRET_ACCESS_KEY=<YOUR_SECRET_KEY>
# RustFS API endpoint
S3_ENDPOINT=https://lobe-s3-api.example.com
# Bucket name
S3_BUCKET=lobe
S3_ENABLE_PATH_STYLE=1
```
</Steps>
+91 -94
View File
@@ -11,133 +11,130 @@ tags:
在服务端数据库中我们需要配置 S3 存储服务来存储文件。
<Callout type={'info'}>
由于近期 MinIO 的商业化策略调整,我们不再推荐使用 MinIO 作为 S3 存储服务,建议所有仍在使用 MinIO 的用户迁移至 [RustFS](https://rustfs.com/) 或者 [ceph](https://ceph.io/) 等开源的 S3 存储服务或者腾讯云对象存储、Cloudflare R2 等云服务商的 S3 存储服务。
由于近期 MinIO 的商业化策略调整,我们不再推荐使用 MinIO 作为 S3 存储服务,建议所有仍在使用 MinIO 的用户迁移至 [RustFS](https://rustfs.com/) 或者 [ceph](https://ceph.io/) 等开源的 S3 存储服务或者腾讯云对象存储、Cloudflare R2 等云服务商的 S3 存储服务。
</Callout>
## 配置步骤
<Steps>
### 部署 RustFS
### 部署 RustFS
首先,拉取 RustFS 的 Docker 镜像:
首先,拉取 RustFS 的 Docker 镜像:
```shell
docker pull rustfs/rustfs:latest
```
```shell
docker pull rustfs/rustfs:latest
```
你可以使用如下命令来查看其版本,建议使用 v1.0.0 及以上版本:
你可以使用如下命令来查看其版本,建议使用 v1.0.0 及以上版本:
```shell
docker inspect --format='{{index .Config.Labels "version"}}' rustfs/rustfs:latest
```
```shell
docker inspect --format='{{index .Config.Labels "version"}}' rustfs/rustfs:latest
```
我们推荐使用 Docker Compose 来部署 RustFS
我们推荐使用 Docker Compose 来部署 RustFS
```yml
services:
rustfs:
image: rustfs/rustfs:latest
container_name: lobe-rustfs
ports:
- '9000:9000'
- '9001:9001'
environment:
- RUSTFS_CONSOLE_ENABLE=true
- RUSTFS_ACCESS_KEY=<YOUR_ACCESS_KEY>
- RUSTFS_SECRET_KEY=<YOUR_SECRET_KEY>
volumes:
- rustfs-data:/data
```yml
services:
rustfs:
image: rustfs/rustfs:latest
container_name: lobe-rustfs
ports:
- '9000:9000'
- '9001:9001'
environment:
- RUSTFS_CONSOLE_ENABLE=true
- RUSTFS_ACCESS_KEY=<YOUR_ACCESS_KEY>
- RUSTFS_SECRET_KEY=<YOUR_SECRET_KEY>
volumes:
- rustfs-data:/data
volumes:
rustfs-data:
```
volumes:
rustfs-data:
```
然后,启动 RustFS
然后,启动 RustFS
```shell
docker compose up -d
```
```shell
docker compose up -d
```
### 创建存储桶
### 创建存储桶
访问 RustFS 的 WebUI`http://localhost:9001/`),即可自动跳转到登录页。输入账号(上述 `docker-compose.yml` 文件中的 `RUSTFS_ACCESS_KEY`)、密码(上述 `docker-compose.yml` 文件中的 `RUSTFS_SECRET_KEY`),即可登录。
访问 RustFS 的 WebUI`http://localhost:9001/`),即可自动跳转到登录页。输入账号(上述 `docker-compose.yml` 文件中的 `RUSTFS_ACCESS_KEY`)、密码(上述 `docker-compose.yml` 文件中的 `RUSTFS_SECRET_KEY`),即可登录。
点击左侧边栏的 `对象存储` 菜单,右上角 `创建存储桶` 按钮,创建一个新的存储桶(Bucket)。创建存储桶时将指定其名称,下文以 `lobe` 为例。版本、对象锁依照默认配置不开启。
点击左侧边栏的 `对象存储` 菜单,右上角 `创建存储桶` 按钮,创建一个新的存储桶(Bucket)。创建存储桶时将指定其名称,下文以 `lobe` 为例。版本、对象锁依照默认配置不开启。
<Image alt={"Create Bucket"} src={'https://github.com/user-attachments/assets/27c37617-a813-4de5-b0bf-c7167999c856'} />
<Image alt={"Create Bucket"} src={'https://github.com/user-attachments/assets/27c37617-a813-4de5-b0bf-c7167999c856'} />
点击存储桶 - `配置` 按钮,选择策略为 `自定义`,然后填入如下 JSON,设置存储桶的权限为 `公有读私有写`:
点击存储桶 - `配置` 按钮,选择策略为 `自定义`,然后填入如下 JSON,设置存储桶的权限为 `公有读私有写`:
```json
{
"ID": "",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": [
"*"
]
},
"Action": [
"s3:GetObject"
],
"NotAction": [],
"Resource": [
"arn:aws:s3:::lobe/*"
],
"NotResource": [],
"Condition": {}
}
]
}
```
```json
{
"ID": "",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": [
"*"
]
},
"Action": [
"s3:GetObject"
],
"NotAction": [],
"Resource": [
"arn:aws:s3:::lobe/*"
],
"NotResource": [],
"Condition": {}
}
]
}
```
点击保存即可。
点击保存即可。
### 设置访问密钥
### 设置访问密钥
<Callout type={'warning'}>
有关这部分,你可以直接使用在 `docker-compose.yml` 文件中配置的 `RUSTFS_ACCESS_KEY` 和 `RUSTFS_SECRET_KEY`,但出于安全考虑,我们推荐你手动创建一个访问密钥。
</Callout>
<Callout type={'warning'}>
有关这部分,你可以直接使用在 `docker-compose.yml` 文件中配置的 `RUSTFS_ACCESS_KEY` 和 `RUSTFS_SECRET_KEY`,但出于安全考虑,我们推荐你手动创建一个访问密钥。
</Callout>
点击左侧边栏的 `访问密钥` 菜单,右上角 `添加访问密钥` 按钮,创建一个新的访问密钥(Access Key)。名称随意,按照默认配置使用主账号策略即可。
点击左侧边栏的 `访问密钥` 菜单,右上角 `添加访问密钥` 按钮,创建一个新的访问密钥(Access Key)。名称随意,按照默认配置使用主账号策略即可。
记录好得到的访问密钥和密钥(你可以点击 `导出` 按钮以在本地保存)。这里 RustFS 的翻译有点迷惑,但你只需要记住上面那个短的是 `Access Key`,长的是 `Secret Key` 即可(导出的 JSON 中是对的)。
记录好得到的访问密钥和密钥(你可以点击 `导出` 按钮以在本地保存)。这里 RustFS 的翻译有点迷惑,但你只需要记住上面那个短的是 `Access Key`,长的是 `Secret Key` 即可(导出的 JSON 中是对的)。
<Image alt={"Add Key"} src={'https://github.com/user-attachments/assets/81f18b20-3918-4f77-8571-07d0c4a79aec'} />
<Image alt={"Add Key"} src={'https://github.com/user-attachments/assets/81f18b20-3918-4f77-8571-07d0c4a79aec'} />
<Image alt={"Export Key"} src={'https://github.com/user-attachments/assets/4dde41ec-985b-4781-8c77-aac65555a32f'} />
<Image alt={"Export Key"} src={'https://github.com/user-attachments/assets/4dde41ec-985b-4781-8c77-aac65555a32f'} />
### 配置反向代理
### 配置反向代理
你还需要完成反向代理配置,并确保局域网 / 公网能访问到 RustFS 的服务。请使用反向代理将以下服务端口映射到域名:
你还需要完成反向代理配置,并确保局域网 / 公网能访问到 RustFS 的服务。请使用反向代理将以下服务端口映射到域名:
| 域名 | 反代端口 | 是否必选 |
| ---------------------- | ------ | ---- |
| `lobe-s3-api.example.com` | `9000` | 必选 |
| `lobe-s3-ui.example.com` | `9001` | |
| 域名 | 反代端口 | 是否必选 |
| ------------------------- | ------ | ---- |
| `lobe-s3-api.example.com` | `9000` | 必选 |
| `lobe-s3-ui.example.com` | `9001` | |
完成反向代理后,记得配置对应的 SSL 证书,启用 HTTPS 访问。
完成反向代理后,记得配置对应的 SSL 证书,启用 HTTPS 访问。
### 设置环境变量
### 设置环境变量
修改 LobeChat 的 `.env` 文件,添加如下环境变量,即可完成配置,使用 RustFS 作为 S3 存储服务:
修改 LobeHub 的 `.env` 文件,添加如下环境变量,即可完成配置,使用 RustFS 作为 S3 存储服务:
```shell
# RustFS 的鉴权 Access Key / Secret Key
S3_ACCESS_KEY_ID=<YOUR_ACCESS_KEY>
S3_SECRET_ACCESS_KEY=<YOUR_SECRET_KEY>
# RustFS API 的请求端点
S3_ENDPOINT=https://lobe-s3-api.example.com
# 存储桶的名称
S3_BUCKET=lobe
# 存储桶对外的访问域名
S3_PUBLIC_DOMAIN=https://lobe-s3-api.example.com
S3_ENABLE_PATH_STYLE=1
```
```shell
# RustFS 的鉴权 Access Key / Secret Key
S3_ACCESS_KEY_ID=<YOUR_ACCESS_KEY>
S3_SECRET_ACCESS_KEY=<YOUR_SECRET_KEY>
# RustFS API 的请求端点
S3_ENDPOINT=https://lobe-s3-api.example.com
# 存储桶的名称
S3_BUCKET=lobe
S3_ENABLE_PATH_STYLE=1
```
</Steps>
@@ -39,7 +39,6 @@ We need to configure S3 storage service for file storage in the server-side data
S3_BUCKET=lobe-130xxxxxx2
S3_ENDPOINT=https://cos.ap-chengdu.myqcloud.com
S3_REGION=ap-chengdu
S3_PUBLIC_DOMAIN=https://lobe-1251234567.cos.ap-chengdu.myqcloud.com
```
<Callout type={'warning'}>
@@ -40,8 +40,6 @@ tags:
S3_ENDPOINT=https://cos.ap-chengdu.myqcloud.com
# 桶的区域
S3_REGION=ap-chengdu
# 存储桶对外的访问域名
S3_PUBLIC_DOMAIN=https://lobe-1251234567.cos.ap-chengdu.myqcloud.com
```
<Callout type={'warning'}>
@@ -42,11 +42,11 @@ Docker 部署版本的升级非常简单,只需要重新部署 LobeHub 的最
<Steps>
### 停止并删除当前运行的 LobeHub 容器
假设 LobeHub 容器的名称是 `lobe-chat`,使用以下指令停止并删除当前运行的 LobeHub 容器:
假设 LobeHub 容器的名称是 `lobehub`,使用以下指令停止并删除当前运行的 LobeHub 容器:
```fish
docker stop lobe-chat
docker rm lobe-chat
docker stop lobehub
docker rm lobehub
```
### 拉取最新的 LobeHub 镜像
@@ -54,7 +54,7 @@ Docker 部署版本的升级非常简单,只需要重新部署 LobeHub 的最
使用以下命令拉取 LobeHub 的最新 Docker 镜像:
```fish
docker pull lobehub/lobe-chat
docker pull lobehub/lobehub
```
### 重新启动 Docker 容器
@@ -65,7 +65,7 @@ Docker 部署版本的升级非常简单,只需要重新部署 LobeHub 的最
docker run -d -p 3210:3210 \
-e OPENAI_API_KEY=sk-xxxx \
-e OPENAI_PROXY_URL=https://api-proxy.com/v1 \
--name lobe-chat \
--name lobehub \
lobehub/lobe-chat
```
</Steps>
@@ -1,8 +1,8 @@
---
title: LobeHub Authentication Service Configuration
description: >-
Learn how to configure external authentication services using Better Auth,
Clerk, or Next Auth for centralized user authorization management. Supported
Learn how to configure external authentication services using Better Auth
for centralized user authorization management. Supported
authentication services include Auth0, Azure ID, etc.
tags:
- Authentication Service
@@ -12,17 +12,7 @@ tags:
# Authentication Service
LobeHub supports the configuration of external authentication services using Better Auth, Clerk, or Next Auth for internal use within enterprises/organizations to centrally manage user authorization.
<Callout type={'info'}>
Looking for legacy authentication methods? See [Legacy Authentication](/docs/self-hosting/advanced/auth/legacy) for NextAuth and Clerk documentation.
</Callout>
Clerk is a comprehensive identity verification solution that has recently gained popularity. It provides a simple yet powerful API and services to handle user authentication and session management. Clerk's design philosophy is to offer a concise and modern authentication solution that enables developers to easily integrate and use it.
LobeHub has deeply integrated with Clerk to provide users with a more secure and convenient login and registration experience. It also relieves developers from the burden of managing authentication logic. Clerk's concise and modern design philosophy aligns perfectly with LobeHub's goals, making user management on the entire platform more efficient and reliable.
By setting the environment variables `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` and `CLERK_SECRET_KEY` in LobeHub's environment, you can enable and use Clerk.
LobeHub supports the configuration of external authentication services using Better Auth for internal use within enterprises/organizations to centrally manage user authorization.
## Better Auth
@@ -40,12 +30,11 @@ By setting the environment variables `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` and `CL
To enable Better Auth in LobeHub, set the following environment variables:
| Environment Variable | Type | Description |
| -------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `NEXT_PUBLIC_ENABLE_BETTER_AUTH` | Required | Set to `1` to enable Better Auth service |
| `AUTH_SECRET` | Required | Key used to encrypt session tokens. Generate using: `openssl rand -base64 32` |
| `NEXT_PUBLIC_AUTH_URL` | Required | The browser-accessible base URL for Better Auth (e.g., `http://localhost:3010`, `https://LobeHub.com`). Optional for Vercel deployments (auto-detected from `VERCEL_URL`) |
| `AUTH_SSO_PROVIDERS` | Optional | Comma-separated list of enabled SSO providers, e.g., `google,github,microsoft` |
| Environment Variable | Type | Description |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `AUTH_SECRET` | Required | Key used to encrypt session tokens. Generate using: `openssl rand -base64 32` |
| `NEXT_PUBLIC_AUTH_URL` | Required | The browser-accessible base URL for Better Auth (e.g., `http://localhost:3010`, `https://LobeHub.com`). Optional for Vercel deployments (auto-detected from `VERCEL_URL`) |
| `AUTH_SSO_PROVIDERS` | Optional | Comma-separated list of enabled SSO providers, e.g., `google,github,microsoft` |
## Supported SSO Providers
@@ -72,6 +61,8 @@ To enable Better Auth in LobeHub, set the following environment variables:
Click on a provider below for detailed configuration guides:
<Cards>
<Card href={'/docs/self-hosting/advanced/auth/providers/password'} title={'Email/Password'} />
<Card href={'/docs/self-hosting/advanced/auth/providers/github'} title={'GitHub'} />
<Card href={'/docs/self-hosting/advanced/auth/providers/google'} title={'Google'} />
@@ -116,63 +107,7 @@ When configuring OAuth providers, use the following callback URL format:
## Email Service Configuration
Used by email verification, password reset, and magic-link delivery. Two providers are supported:
### Option 1: Nodemailer (SMTP)
Send emails via SMTP protocol, suitable for users with existing email services. See [Nodemailer SMTP docs](https://nodemailer.com/smtp/).
| Environment Variable | Type | Description | Example |
| ------------------------ | -------- | -------------------------------------------------------------- | --------------------- |
| `EMAIL_SERVICE_PROVIDER` | Optional | Set to `nodemailer` (default) | `nodemailer` |
| `SMTP_HOST` | Required | SMTP server hostname | `smtp.gmail.com` |
| `SMTP_PORT` | Required | SMTP server port (`587` for TLS, `465` for SSL) | `587` |
| `SMTP_SECURE` | Optional | `true` for SSL (port 465), `false` for TLS (port 587) | `false` |
| `SMTP_USER` | Required | SMTP auth username | `user@gmail.com` |
| `SMTP_PASS` | Required | SMTP auth password | `your-app-password` |
| `SMTP_FROM` | Optional | Sender address (required for AWS SES), defaults to `SMTP_USER` | `noreply@example.com` |
<Callout type={'warning'}>
When using Gmail, you must use an App Password instead of your account password. Generate one at [Google App Passwords](https://myaccount.google.com/apppasswords).
</Callout>
### Option 2: Resend
[Resend](https://resend.com/) is a modern email API service with simple setup, recommended for new users.
| Environment Variable | Type | Description | Example |
| ------------------------ | ----------- | ----------------------------------------- | --------------------------- |
| `EMAIL_SERVICE_PROVIDER` | Required | Set to `resend` | `resend` |
| `RESEND_API_KEY` | Required | Resend API Key | `re_xxxxxxxxxxxxxxxxxxxxxx` |
| `RESEND_FROM` | Recommended | Sender address, must be a verified domain | `noreply@your-domain.com` |
<Callout type={'info'}>
Before using Resend, you need to [verify your sending domain](https://resend.com/docs/dashboard/domains/introduction), otherwise emails can only be sent to your own address.
</Callout>
### Common Configuration
Before using Better Auth, please set the following variables in LobeHub's environment variables:
## Email Verification
Enable email verification to ensure users own the email addresses they register with (off by default):
| Environment Variable | Type | Description |
| ------------------------- | -------- | ----------------------------------------------------------- |
| `AUTH_EMAIL_VERIFICATION` | Optional | Set to `1` to require email verification after registration |
<Callout type={'info'}>
Email verification requires a working email service (SMTP or Resend) configured above. When enabled, users must verify their email address before they can sign in.
</Callout>
## Magic Link (Passwordless) Login
Enable magic-link login (depends on a working email provider above, off by default):
| Environment Variable | Type | Description |
| ------------------------ | -------- | ------------------------------------------------------------------- |
| `AUTH_ENABLE_MAGIC_LINK` | Optional | Set to `1` to enable passwordless magic-link login (off by default) |
Email service is used for email verification, password reset, and magic link delivery. For detailed configuration, see [Email Service Configuration](/docs/self-hosting/auth/email).
<Callout type={'tip'}>
Go to [Environment Variables](/docs/self-hosting/environment-variables/auth#better-auth) for detailed information on all Better Auth variables.
@@ -216,6 +151,16 @@ The current authentication system requires email. Please configure a valid email
This applies to all authentication methods, including SSO providers like Casdoor. Always ensure users have valid email addresses configured.
### How do I enable SSO-only mode (disable email/password login)?
Set `AUTH_DISABLE_EMAIL_PASSWORD=1` to disable email/password authentication. When enabled:
- The email input will be hidden on the login page, only SSO buttons are displayed
- The signup page will redirect to the login page
- Users can only log in via configured SSO providers
Make sure you have at least one SSO provider configured via `AUTH_SSO_PROVIDERS` before enabling this option.
### How do I restrict registration to specific emails or domains?
Set the `AUTH_ALLOWED_EMAILS` environment variable with a comma-separated list of allowed emails or domains. For example:
@@ -233,10 +178,8 @@ Set the `AUTH_ALLOWED_EMAILS` environment variable with a comma-separated list o
Allow LobeHub to receive notifications when user information is updated in the identity provider. Supported providers include Casdoor and Logto. Please refer to the specific provider documentation for configuration details.
### Database Session
### Other SSO Providers
Allow the session store in database, see also the [Auth.js Session Documentation](https://authjs.dev/concepts/session-strategies#database-session).
If you need to use an SSO provider not included in the list above, you can use [Generic OIDC](/docs/self-hosting/auth/providers/generic-oidc) to configure any OpenID Connect or OAuth 2.0 compliant provider.
## Other SSO Providers
Please refer to the [Auth.js](https://authjs.dev/getting-started/authentication/oauth) documentation and feel free to submit a Pull Request.
Feel free to submit a Pull Request to add more built-in SSO provider support. For details, see the [Better Auth documentation](https://www.better-auth.com/docs/concepts/oauth).
@@ -1,7 +1,7 @@
---
title: LobeHub 身份验证服务配置
description: >-
了解如何使用 Better Auth、Clerk 或 Next Auth 配置外部身份验证服务,以统一管理用户授权。支持的身份验证服务包括 Auth0、
了解如何使用 Better Auth 配置外部身份验证服务,以统一管理用户授权。支持的身份验证服务包括 Auth0、
Azure ID 等。
tags:
- 身份验证服务
@@ -12,17 +12,7 @@ tags:
# 身份验证服务
LobeHub 支持使用 Better Auth、Clerk 或者 Next Auth 配置外部身份验证服务,供企业 / 组织内部使用,统一管理用户授权。
<Callout type={'info'}>
需要使用旧版身份验证方案?请参阅 [旧版身份验证](/zh/docs/self-hosting/advanced/auth/legacy) 了解 NextAuth 和 Clerk 的文档。
</Callout>
Clerk 是一个近期流行起来的全面的身份验证解决方案,它提供了简单而强大的 API 和服务来处理用户认证和会话管理。Clerk 的设计哲学是提供一套简洁、现代的认证解决方案,使得开发者可以轻松集成和使用。
LobeHub 与 Clerk 做了深度集成,能够为用户提供一个更加安全、便捷的登录和注册体验,同时也为开发者减轻了管理身份验证逻辑的负担。Clerk 的简洁和现代的设计理念与 LobeHub 的目标非常契合,使得整个平台的用户管理更加高效和可靠。
在 LobeHub 的环境变量中设置 `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` 和 `CLERK_SECRET_KEY`,即可开启和使用 Clerk。
LobeHub 支持使用 Better Auth 配置外部身份验证服务,供企业 / 组织内部使用,统一管理用户授权。
## Better Auth
@@ -40,12 +30,11 @@ LobeHub 与 Clerk 做了深度集成,能够为用户提供一个更加安全
要在 LobeHub 中启用 Better Auth,请设置以下环境变量:
| 环境变量 | 类型 | 描述 |
| -------------------------------- | -- | --------------------------------------------------------------------------------------------------------------- |
| `NEXT_PUBLIC_ENABLE_BETTER_AUTH` | 必选 | 设置为 `1` 以启用 Better Auth 服务 |
| `AUTH_SECRET` | 必选 | 用于加密会话令牌的密钥。使用以下命令生成:`openssl rand -base64 32` |
| `NEXT_PUBLIC_AUTH_URL` | 选 | 浏览器可访问的 Better Auth 基础 URL(例如 `http://localhost:3010`、`https://LobeHub.com`)。Vercel 部署时可选(会自动从 `VERCEL_URL` 获取) |
| `AUTH_SSO_PROVIDERS` | 可选 | 启用的 SSO 提供商列表,以逗号分隔,例如 `google,github,microsoft` |
| 环境变量 | 类型 | 描述 |
| ---------------------- | -- | --------------------------------------------------------------------------------------------------------------- |
| `AUTH_SECRET` | 必选 | 用于加密会话令牌的密钥。使用以下命令生成:`openssl rand -base64 32` |
| `NEXT_PUBLIC_AUTH_URL` | 必选 | 浏览器可访问的 Better Auth 基础 URL(例如 `http://localhost:3010`、`https://LobeHub.com`)。Vercel 部署时可选(会自动从 `VERCEL_URL` 获取) |
| `AUTH_SSO_PROVIDERS` | 选 | 启用的 SSO 提供商列表,以逗号分隔,例如 `google,github,microsoft` |
## 支持的 SSO 提供商
@@ -72,6 +61,8 @@ LobeHub 与 Clerk 做了深度集成,能够为用户提供一个更加安全
点击下方提供商查看详细配置指南:
<Cards>
<Card href={'/zh/docs/self-hosting/advanced/auth/providers/password'} title={'邮箱密码'} />
<Card href={'/zh/docs/self-hosting/advanced/auth/providers/github'} title={'GitHub'} />
<Card href={'/zh/docs/self-hosting/advanced/auth/providers/google'} title={'Google'} />
@@ -116,63 +107,7 @@ LobeHub 与 Clerk 做了深度集成,能够为用户提供一个更加安全
## 邮件服务配置
用于邮箱验证、密码重置和魔法链接发送。支持两种邮件服务:
### 方式一:NodemailerSMTP
使用 SMTP 协议发送邮件,适合已有邮箱服务的用户。参考 [Nodemailer SMTP 文档](https://nodemailer.com/smtp/)。
| 环境变量 | 类型 | 描述 | 示例 |
| ------------------------ | -- | ---------------------------------------------- | --------------------- |
| `EMAIL_SERVICE_PROVIDER` | 可选 | 设置为 `nodemailer`(默认值) | `nodemailer` |
| `SMTP_HOST` | 必选 | SMTP 服务器主机名 | `smtp.gmail.com` |
| `SMTP_PORT` | 必选 | SMTP 服务器端口(TLS 通常为 `587`SSL 为 `465` | `587` |
| `SMTP_SECURE` | 可选 | SSL 设置为 `true`(端口 465),TLS 设置为 `false`(端口 587 | `false` |
| `SMTP_USER` | 必选 | SMTP 认证用户名 | `user@gmail.com` |
| `SMTP_PASS` | 必选 | SMTP 认证密码 | `your-app-password` |
| `SMTP_FROM` | 可选 | 发件人地址(AWS SES 必填),默认为 `SMTP_USER` | `noreply@example.com` |
<Callout type={'warning'}>
使用 Gmail 时,需使用应用专用密码而非账户密码。前往 [Google 应用专用密码](https://myaccount.google.com/apppasswords) 生成。
</Callout>
### 方式二:Resend
[Resend](https://resend.com/) 是一个现代邮件 API 服务,配置简单,推荐新用户使用。
| 环境变量 | 类型 | 描述 | 示例 |
| ------------------------ | -- | ------------------------- | --------------------------- |
| `EMAIL_SERVICE_PROVIDER` | 必选 | 设置为 `resend` | `resend` |
| `RESEND_API_KEY` | 必选 | Resend API Key | `re_xxxxxxxxxxxxxxxxxxxxxx` |
| `RESEND_FROM` | 推荐 | 发件人地址,需为 Resend 已验证域名下的邮箱 | `noreply@your-domain.com` |
<Callout type={'info'}>
使用 Resend 前需先 [验证发件域名](https://resend.com/docs/dashboard/domains/introduction),否则只能发送到自己的邮箱。
</Callout>
### 通用配置
在使用 Better Auth 之前,请先在 LobeHub 的环境变量中设置以下变量:
## 邮箱验证
启用邮箱验证以确保用户拥有其注册的邮箱地址(默认关闭):
| 环境变量 | 类型 | 描述 |
| ------------------------- | -- | -------------------- |
| `AUTH_EMAIL_VERIFICATION` | 可选 | 设置为 `1` 以要求注册后进行邮箱验证 |
<Callout type={'info'}>
邮箱验证需要上方已配置好的邮件服务(SMTP 或 Resend)。启用后,用户必须验证其邮箱地址才能登录。
</Callout>
## 魔法链接(免密)登录
启用魔法链接登录(依赖上方已配置好的邮件服务,默认关闭):
| 环境变量 | 类型 | 描述 |
| ------------------------ | -- | ----------------------- |
| `AUTH_ENABLE_MAGIC_LINK` | 可选 | 设置为 `1` 以启用魔法链接登录(默认关闭) |
邮件服务用于邮箱验证、密码重置和魔法链接发送。详细配置请参阅 [邮件服务配置](/zh/docs/self-hosting/auth/email)。
<Callout type={'tip'}>
前往 [环境变量](/zh/docs/self-hosting/environment-variables/auth#better-auth) 可查阅所有 Better Auth 相关变量详情。
@@ -217,6 +152,16 @@ Better Auth 支持内置提供商(Google、GitHub、Microsoft、Apple、AWS Co
这适用于所有身份验证方式,包括 Casdoor 等 SSO 提供商。请确保用户配置了有效的邮箱地址。
### 如何启用仅 SSO 模式(禁用邮箱密码登录)?
设置 `AUTH_DISABLE_EMAIL_PASSWORD=1` 可禁用邮箱密码登录。启用后:
- 登录页面将隐藏邮箱输入框,仅显示 SSO 登录按钮
- 注册页面将重定向到登录页面
- 用户只能通过配置的 SSO 提供商登录
启用此选项前,请确保已通过 `AUTH_SSO_PROVIDERS` 配置了至少一个 SSO 提供商。
### 如何限制只允许特定邮箱或域名注册?
设置 `AUTH_ALLOWED_EMAILS` 环境变量,支持完整邮箱地址或域名,以逗号分隔。例如:
@@ -232,10 +177,8 @@ Better Auth 支持内置提供商(Google、GitHub、Microsoft、Apple、AWS Co
允许 LobeHub 在身份提供商中用户信息更新时接收通知。支持的提供商包括 Casdoor 和 Logto。请参考具体提供商文档进行配置。
### 数据库会话
### 其他 SSO 提供商
允许会话存储在数据库中,详情请参阅 [Auth.js 会话文档](https://authjs.dev/concepts/session-strategies#database-session)
如果你需要使用上述列表中未包含的 SSO 提供商,可以使用 [Generic OIDC](/zh/docs/self-hosting/auth/providers/generic-oidc) 来配置任何符合 OpenID Connect 或 OAuth 2.0 标准的提供商
## 其他 SSO 提供商
请参考 [Auth.js](https://authjs.dev/getting-started/authentication/oauth) 文档,欢迎提交 Pull Request。
欢迎提交 Pull Request 来添加更多内置 SSO 提供商支持。详情请参考 [Better Auth 文档](https://www.better-auth.com/docs/concepts/oauth)。
+70
View File
@@ -0,0 +1,70 @@
---
title: Email Service Configuration
description: Configure LobeHub email service for email verification, password reset, and magic link login.
tags:
- Email Service
- SMTP
- Resend
- Email Verification
- Magic Link
---
# Email Service Configuration
Email service is used for email verification, password reset, and magic link delivery. LobeHub supports two email service providers.
## Nodemailer (SMTP)
Send emails via SMTP protocol, suitable for users with existing email services. See [Nodemailer SMTP docs](https://nodemailer.com/smtp/).
| Environment Variable | Type | Description | Example |
| ------------------------ | -------- | -------------------------------------------------------------- | --------------------- |
| `EMAIL_SERVICE_PROVIDER` | Optional | Set to `nodemailer` (default) | `nodemailer` |
| `SMTP_HOST` | Required | SMTP server hostname | `smtp.gmail.com` |
| `SMTP_PORT` | Required | SMTP server port (`587` for TLS, `465` for SSL) | `587` |
| `SMTP_SECURE` | Optional | `true` for SSL (port 465), `false` for TLS (port 587) | `false` |
| `SMTP_USER` | Required | SMTP auth username | `user@gmail.com` |
| `SMTP_PASS` | Required | SMTP auth password | `your-app-password` |
| `SMTP_FROM` | Optional | Sender address (required for AWS SES), defaults to `SMTP_USER` | `noreply@example.com` |
<Callout type={'warning'}>
When using Gmail, you must use an App Password instead of your account password. Generate one at [Google App Passwords](https://myaccount.google.com/apppasswords).
</Callout>
## Resend
[Resend](https://resend.com/) is a modern email API service with simple setup, recommended for new users.
| Environment Variable | Type | Description | Example |
| ------------------------ | ----------- | ----------------------------------------- | --------------------------- |
| `EMAIL_SERVICE_PROVIDER` | Required | Set to `resend` | `resend` |
| `RESEND_API_KEY` | Required | Resend API Key | `re_xxxxxxxxxxxxxxxxxxxxxx` |
| `RESEND_FROM` | Recommended | Sender address, must be a verified domain | `noreply@your-domain.com` |
<Callout type={'info'}>
Before using Resend, you need to [verify your sending domain](https://resend.com/docs/dashboard/domains/introduction), otherwise emails can only be sent to your own address.
</Callout>
## Email Verification
Enable email verification to ensure users own the email addresses they register with (off by default):
| Environment Variable | Type | Description |
| ------------------------- | -------- | ----------------------------------------------------------- |
| `AUTH_EMAIL_VERIFICATION` | Optional | Set to `1` to require email verification after registration |
<Callout type={'info'}>
Email verification requires a working email service (SMTP or Resend) configured above. When enabled, users must verify their email address before they can sign in.
</Callout>
## Magic Link (Passwordless) Login
Enable magic-link login (depends on a working email provider above, off by default):
| Environment Variable | Type | Description |
| ------------------------ | -------- | ------------------------------------------------------------------- |
| `AUTH_ENABLE_MAGIC_LINK` | Optional | Set to `1` to enable passwordless magic-link login (off by default) |
<Callout type={'tip'}>
Go to [Environment Variables](/docs/self-hosting/environment-variables/auth#better-auth) for detailed information on all Better Auth variables.
</Callout>

Some files were not shown because too many files have changed in this diff Show More