mirror of
https://github.com/lobehub/lobe-chat.git
synced 2026-06-15 04:00:09 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d6732b14a1 |
+6
-4
@@ -1,3 +1,6 @@
|
||||
# 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
|
||||
|
||||
@@ -262,6 +265,9 @@ 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
|
||||
@@ -289,10 +295,6 @@ 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:
|
||||
|
||||
@@ -85,6 +85,9 @@ 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
|
||||
|
||||
|
||||
@@ -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-15", "name": "macos-arm64"}'
|
||||
arm_entry='{"os": "macos-14", "name": "macos-arm64"}'
|
||||
static_matrix=$(echo "$static_matrix" | jq -c --argjson entry "$arm_entry" '. + [$entry]')
|
||||
fi
|
||||
|
||||
|
||||
-259
@@ -2,265 +2,6 @@
|
||||
|
||||
# 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">
|
||||
|
||||
[](#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">
|
||||
|
||||
[](#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">
|
||||
|
||||
[](#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">
|
||||
|
||||
[](#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">
|
||||
|
||||
[](#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">
|
||||
|
||||
[](#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">
|
||||
|
||||
[](#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">
|
||||
|
||||
[](#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">
|
||||
|
||||
[](#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">
|
||||
|
||||
[](#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>
|
||||
|
||||
+56
-50
@@ -8,22 +8,24 @@ ARG USE_CN_MIRROR
|
||||
|
||||
ENV DEBIAN_FRONTEND="noninteractive"
|
||||
|
||||
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/*
|
||||
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
|
||||
|
||||
## Builder image, install all the dependencies and build the app
|
||||
FROM base AS builder
|
||||
@@ -75,21 +77,23 @@ 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 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
|
||||
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
|
||||
|
||||
COPY . .
|
||||
|
||||
@@ -97,15 +101,17 @@ COPY . .
|
||||
RUN npm run build:docker
|
||||
|
||||
# Prepare desktop export assets for Electron packaging (if generated)
|
||||
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
|
||||
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
|
||||
|
||||
## Application image, copy all the files for production
|
||||
FROM busybox:latest AS app
|
||||
@@ -132,10 +138,12 @@ 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 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
|
||||
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
|
||||
|
||||
## Production image, copy all the files and run next
|
||||
FROM scratch
|
||||
@@ -158,12 +166,14 @@ ENV HOSTNAME="0.0.0.0" \
|
||||
PORT="3210"
|
||||
|
||||
# General Variables
|
||||
ENV APP_URL="" \
|
||||
ENV ACCESS_CODE="" \
|
||||
APP_URL="" \
|
||||
API_KEY_SELECT_MODE="" \
|
||||
DEFAULT_AGENT_CONFIG="" \
|
||||
SYSTEM_AGENT="" \
|
||||
FEATURE_FLAGS="" \
|
||||
PROXY_URL=""
|
||||
PROXY_URL="" \
|
||||
ENABLE_AUTH_PROTECTION=""
|
||||
|
||||
# Database
|
||||
ENV KEY_VAULTS_SECRET="" \
|
||||
@@ -174,10 +184,6 @@ 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="" \
|
||||
|
||||
@@ -37,7 +37,7 @@ We’re building the world’s largest human–agent co-evolving network.
|
||||
[![][share-mastodon-shield]][share-mastodon-link]
|
||||
[![][share-linkedin-shield]][share-linkedin-link]
|
||||
|
||||
<sup>Agent teammates that grow with you</sup>
|
||||
<sup>Agent teams 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) 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) and `ACCESS_CODE` (recommended) 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,6 +647,7 @@ 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]
|
||||
@@ -828,7 +829,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&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-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-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
|
||||
|
||||
+4
-3
@@ -35,7 +35,7 @@ LobeHub 是一个工作与生活空间,用于发现、构建并与会随着您
|
||||
[![][share-weibo-shield]][share-weibo-link]
|
||||
[![][share-mastodon-shield]][share-mastodon-link]
|
||||
|
||||
<sup>Agent teammates that grow with you</sup>
|
||||
<sup>Agent teams 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` (必填);
|
||||
- 点击下方按钮开始部署: 直接使用 GitHub 账号登录即可,记得在环境变量页填入 `OPENAI_API_KEY` (必填) and `ACCESS_CODE`(推荐);
|
||||
- 部署完毕后,即可开始使用;
|
||||
- 绑定自定义域名(可选):Vercel 分配的域名 DNS 在某些区域被污染了,绑定自定义域名即可直连。目前 Zeabur 提供的域名还未被污染,大多数地区都可以直连。
|
||||
|
||||
@@ -621,6 +621,7 @@ 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]
|
||||
@@ -842,7 +843,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&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-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-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
|
||||
|
||||
@@ -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,6 +47,9 @@
|
||||
"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",
|
||||
@@ -100,9 +103,6 @@
|
||||
"vitest": "^3.2.4",
|
||||
"zod": "^3.25.76"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"node-mac-permissions": "^2.5.0"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"@napi-rs/canvas",
|
||||
|
||||
@@ -218,13 +218,8 @@ export default class LocalFileCtr extends ControllerModule {
|
||||
}
|
||||
|
||||
@IpcMethod()
|
||||
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 });
|
||||
async listLocalFiles({ path: dirPath }: ListLocalFileParams): Promise<FileResult[]> {
|
||||
logger.debug('Listing directory contents:', { dirPath });
|
||||
|
||||
const results: FileResult[] = [];
|
||||
try {
|
||||
@@ -261,51 +256,22 @@ export default class LocalFileCtr extends ControllerModule {
|
||||
}
|
||||
}
|
||||
|
||||
// Sort entries based on sortBy and sortOrder
|
||||
// Sort entries: folders first, then by name
|
||||
results.sort((a, b) => {
|
||||
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();
|
||||
}
|
||||
if (a.isDirectory !== b.isDirectory) {
|
||||
return a.isDirectory ? -1 : 1; // Directories first
|
||||
}
|
||||
|
||||
return sortOrder === 'desc' ? -comparison : comparison;
|
||||
// Add null/undefined checks for robustness if needed, though names should exist
|
||||
return (a.name || '').localeCompare(b.name || ''); // Then sort by name
|
||||
});
|
||||
|
||||
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 };
|
||||
logger.debug('Directory listing successful', { dirPath, resultCount: results.length });
|
||||
return results;
|
||||
} 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 result on error listing directory itself
|
||||
return { files: [], totalCount: 0 };
|
||||
// For now, returning empty array on error listing directory itself
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,14 +59,14 @@ interface McpInstallParams {
|
||||
*/
|
||||
export default class McpInstallController extends ControllerModule {
|
||||
/**
|
||||
* Handle MCP plugin installation request
|
||||
* @param parsedData Parsed protocol data
|
||||
* @returns Whether processing succeeded
|
||||
* 处理 MCP 插件安装请求
|
||||
* @param parsedData 解析后的协议数据
|
||||
* @returns 是否处理成功
|
||||
*/
|
||||
@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';
|
||||
|
||||
// For official marketplace, schema is optional; for third-party marketplace, schema is required
|
||||
// 对于官方市场,schema 是可选的;对于第三方市场,schema 是必需的
|
||||
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;
|
||||
|
||||
// If schema parameter is provided, parse and validate
|
||||
// 如果提供了 schema 参数,则解析和验证
|
||||
if (schemaParam) {
|
||||
try {
|
||||
mcpSchema = JSON.parse(schemaParam);
|
||||
@@ -104,7 +104,7 @@ export default class McpInstallController extends ControllerModule {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify identifier matches id parameter
|
||||
// 验证 identifier 与 id 参数匹配
|
||||
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. Listen for request errors (e.g., DNS resolution failure)
|
||||
// 5. 监听请求本身的错误(如 DNS 解析失败)
|
||||
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,514 +553,6 @@ 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({
|
||||
|
||||
@@ -1,72 +1,4 @@
|
||||
[
|
||||
{
|
||||
"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."]
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
# 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"}]}
|
||||
@@ -1,34 +0,0 @@
|
||||
# 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"}]}
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"ID": "",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": ["*"]
|
||||
},
|
||||
"Action": ["s3:GetObject"],
|
||||
"NotAction": [],
|
||||
"Resource": ["arn:aws:s3:::lobe/*"],
|
||||
"NotResource": [],
|
||||
"Condition": {}
|
||||
}
|
||||
],
|
||||
"Version": "2012-10-17"
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
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
@@ -37,6 +37,7 @@ 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
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ 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,6 +34,7 @@ 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,6 +34,7 @@ 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,6 +103,7 @@ 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'
|
||||
|
||||
@@ -21,7 +21,8 @@ AUTH_ZITADEL_ISSUER=http://localhost:8080
|
||||
S3_ACCESS_KEY_ID=
|
||||
S3_SECRET_ACCESS_KEY=
|
||||
S3_ENDPOINT=http://localhost:9000
|
||||
S3_BUCKET=lobe
|
||||
S3_BUCKET=lobe
|
||||
S3_PUBLIC_DOMAIN=http://localhost:9000
|
||||
S3_ENABLE_PATH_STYLE=1
|
||||
LLM_VISION_IMAGE_USE_BASE64=1
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ AUTH_ZITADEL_ISSUER=http://localhost:8080
|
||||
S3_ACCESS_KEY_ID=
|
||||
S3_SECRET_ACCESS_KEY=
|
||||
S3_ENDPOINT=http://localhost:9000
|
||||
S3_BUCKET=lobe
|
||||
S3_BUCKET=lobe
|
||||
S3_PUBLIC_DOMAIN=http://localhost:9000
|
||||
S3_ENABLE_PATH_STYLE=1
|
||||
LLM_VISION_IMAGE_USE_BASE64=1
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ 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,6 +34,7 @@ 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,6 +38,8 @@ 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,6 +38,8 @@ 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,6 +35,8 @@ 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,6 +31,8 @@ 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
|
||||
|
||||
+90
-53
@@ -230,20 +230,6 @@ 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)
|
||||
@@ -277,10 +263,10 @@ show_message() {
|
||||
tips_allow_ports)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "请确保服务器以下端口未被占用且能被访问:3210, 9000, 9001"
|
||||
echo "请确保服务器以下端口未被占用且能被访问:3210, 9000, 9001, 8000"
|
||||
;;
|
||||
*)
|
||||
echo "Please make sure the following ports on the server are not occupied and can be accessed: 3210, 9000, 9001"
|
||||
echo "Please make sure the following ports on the server are not occupied and can be accessed: 3210, 9000, 9001, 8000"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
@@ -329,10 +315,12 @@ show_message() {
|
||||
tips_init_database_failed)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "无法初始化数据库"
|
||||
echo "无法初始化数据库,为了避免你的数据重复初始化,请在首次成功启动时运行以下指令清空 Casdoor 初始配置文件:"
|
||||
echo "echo '{}' > init_data.json"
|
||||
;;
|
||||
*)
|
||||
echo "Failed to initialize the database."
|
||||
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"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
@@ -350,7 +338,7 @@ show_message() {
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "请选择部署模式:"
|
||||
echo "(0) 域名模式(访问时无需指明端口),需要使用反向代理服务 LobeHub, RustFS,并分别分配一个域名;"
|
||||
echo "(0) 域名模式(访问时无需指明端口),需要使用反向代理服务 LobeHub, RustFS, Casdoor ,并分别分配一个域名;"
|
||||
echo "(1) 端口模式(访问时需要指明端口,如使用IP访问,或域名+端口访问),需要放开指定端口;"
|
||||
echo "(2) 本地模式(仅供本地测试使用)"
|
||||
echo "如果你对这些内容疑惑,可以先选择使用本地模式进行部署,稍后根据文档指引再进行修改。"
|
||||
@@ -358,7 +346,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, 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, Casdoor, 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."
|
||||
@@ -420,33 +408,31 @@ 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
|
||||
|
||||
# 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
|
||||
|
||||
# Check if the color is valid
|
||||
if [[ -z "${colors[$color]}" ]]; then
|
||||
echo "Invalid color specified. Available colors: ${!colors[@]}"
|
||||
return 1
|
||||
fi
|
||||
# Print the text with padding
|
||||
printf "%*s${color_code}%s${reset_code}\n" $padding "" "$text"
|
||||
printf "%*s${colors[$color]}%s${colors[reset]}\n" $padding "" "$text"
|
||||
}
|
||||
|
||||
# Usage:
|
||||
@@ -483,9 +469,10 @@ ask() {
|
||||
# == Variables ==
|
||||
# ===============
|
||||
# File list
|
||||
SUB_DIR="docker-compose/deploy"
|
||||
SUB_DIR="docker-compose/local"
|
||||
FILES=(
|
||||
"$SUB_DIR/docker-compose.yml"
|
||||
"$SUB_DIR/init_data.json"
|
||||
"$SUB_DIR/searxng-settings.yml"
|
||||
"$SUB_DIR/bucket.config.json"
|
||||
)
|
||||
@@ -494,7 +481,10 @@ 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"
|
||||
|
||||
@@ -524,8 +514,9 @@ section_download_files(){
|
||||
fi
|
||||
|
||||
download_file "$SOURCE_URL/${FILES[0]}" "docker-compose.yml"
|
||||
download_file "$SOURCE_URL/${FILES[1]}" "searxng-settings.yml"
|
||||
download_file "$SOURCE_URL/${FILES[2]}" "bucket.config.json"
|
||||
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 .env.example with the specified language
|
||||
if [ "$LANGUAGE" = "zh_CN" ]; then
|
||||
download_file "$SOURCE_URL/${ENV_EXAMPLES[0]}" ".env"
|
||||
@@ -585,10 +576,15 @@ 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
|
||||
# If user use domain mode, ask for the domain of RustFS and Casdoor
|
||||
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"
|
||||
@@ -599,16 +595,23 @@ 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
|
||||
|
||||
|
||||
@@ -661,7 +664,37 @@ 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
|
||||
@@ -702,10 +735,13 @@ section_init_database() {
|
||||
fi
|
||||
|
||||
docker compose pull
|
||||
docker compose up --detach postgresql
|
||||
docker compose up --detach postgresql casdoor
|
||||
# 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"
|
||||
@@ -723,14 +759,16 @@ fi
|
||||
section_display_configurated_report() {
|
||||
# Display configuration reports
|
||||
echo $(show_message "security_secrect_regenerate_report")
|
||||
|
||||
echo -e "LobeHub: \n - URL: $PROTOCOL://$LOBE_HOST"
|
||||
|
||||
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 "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
|
||||
|
||||
@@ -739,8 +777,7 @@ 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" "$(show_message "tips_regen_jwks")"
|
||||
printf "\n%s\n\n" "$(show_message "tips_disable_registration")"
|
||||
printf "\n%s\n\n" "$(show_message "tips_regen_jwks")"
|
||||
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"
|
||||
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# Seamless DeepSeek R1 Integration, Unlock a New Chain-of-Thought Experience
|
||||
|
||||
LobeHub completed its largest AI ecosystem expansion ever in February, delivering a more powerful and flexible AI chat experience.
|
||||
LobeChat 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 ,开启思维链新体验
|
||||
|
||||
LobeHub 在二月完成了史上最大规模的 AI 生态扩展,带来更强大、更灵活的 AI 对话体验。
|
||||
LobeChat 在二月完成了史上最大规模的 AI 生态扩展,带来更强大、更灵活的 AI 对话体验。
|
||||
|
||||
## 🌟 重大更新
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# Seamless DeepSeek R1 Integration, Unlock a New Chain-of-Thought Experience
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## 🌟 Key Updates
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# 完美集成 DeepSeek R1 ,开启思维链新体验
|
||||
|
||||
LobeHub 在三月持续优化用户体验,新增快捷键自定义、数据导出等实用功能,并扩展 AI 服务商生态。
|
||||
LobeChat 在三月持续优化用户体验,新增快捷键自定义、数据导出等实用功能,并扩展 AI 服务商生态。
|
||||
|
||||
## 🌟 重要更新
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Brand-New Design Style and Desktop App Release ✨
|
||||
description: LobeHub officially launches the desktop app, delivering a more modern and smoother experience.
|
||||
description: LobeChat 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, 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.
|
||||
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.
|
||||
|
||||
## 🌟 Major Updates
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: 全新设计风格与桌面端发布 ✨
|
||||
description: LobeHub 正式发布桌面端应用,带来更现代、更流畅的使用体验
|
||||
description: LobeChat 正式发布桌面端应用,带来更现代、更流畅的使用体验
|
||||
tags:
|
||||
- 桌面端
|
||||
- LobeHub
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# 全新设计风格与桌面端发布 ✨
|
||||
|
||||
LobeHub 在四月完成重大视觉升级,推出全新 Lobe UI v2 设计系统,并正式发布桌面端应用,带来更现代、更流畅的使用体验。
|
||||
LobeChat 在四月完成重大视觉升级,推出全新 Lobe UI v2 设计系统,并正式发布桌面端应用,带来更现代、更流畅的使用体验。
|
||||
|
||||
## 🌟 重大更新
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# Prompt Variables and Claude 4 Reasoning Model Support 🚀
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## 🌟 Key Updates
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# 提示词变量与 Claude 4 推理模型支持 🚀
|
||||
|
||||
LobeHub 在五月至六月持续优化核心功能,新增提示词变量系统、支持 Claude 4 推理模型,并扩展多个 AI 服务商的搜索与推理能力。
|
||||
LobeChat 在五月至六月持续优化核心功能,新增提示词变量系统、支持 Claude 4 推理模型,并扩展多个 AI 服务商的搜索与推理能力。
|
||||
|
||||
## 🌟 主要更新
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# MCP Marketplace and Search Provider Expansion 🔍
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## 🌟 Major Updates
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# MCP 市场与搜索服务商扩展 🔍
|
||||
|
||||
LobeHub 在六月至七月推出 MCP 插件市场,新增多个搜索服务商支持,并集成 Amazon Cognito 与 Google SSO 认证,持续优化用户体验与开发者生态。
|
||||
LobeChat 在六月至七月推出 MCP 插件市场,新增多个搜索服务商支持,并集成 Amazon Cognito 与 Google SSO 认证,持续优化用户体验与开发者生态。
|
||||
|
||||
## 🌟 重大更新
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# AI Image Generation and Desktop Enhancements 🎨
|
||||
|
||||
From July to August, LobeHub introduced AI image generation, added support for multiple providers, and continued improving the desktop experience and authentication system.
|
||||
From July to August, LobeChat 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 图像生成与桌面端增强 🎨
|
||||
|
||||
LobeHub 在七月至八月推出 AI 图像生成功能,新增多个服务商支持,并持续优化桌面端体验与认证系统。
|
||||
LobeChat 在七月至八月推出 AI 图像生成功能,新增多个服务商支持,并持续优化桌面端体验与认证系统。
|
||||
|
||||
## 🌟 重大更新
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# Gemini Image Generation and Non-Streaming Mode Support 🎨
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## 🌟 Major Updates
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# Gemini 图像生成与非流式模式支持 🎨
|
||||
|
||||
LobeHub 在八月至九月新增 Gemini 2.5 Flash Image 图像生成能力,支持非流式响应模式,并扩展多个 AI 服务商与模型支持。
|
||||
LobeChat 在八月至九月新增 Gemini 2.5 Flash Image 图像生成能力,支持非流式响应模式,并扩展多个 AI 服务商与模型支持。
|
||||
|
||||
## 🌟 重大更新
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# Claude Sonnet 4.5 and Built-in Python Plugin 🐍
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## 🌟 Key Updates
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# Claude Sonnet 4.5 与内置 Python 插件 🐍
|
||||
|
||||
LobeHub 在九月至十月新增 Claude Sonnet 4.5 模型支持,推出内置 Python 插件,并优化聊天列表导航与富文本编辑体验。
|
||||
LobeChat 在九月至十月新增 Claude Sonnet 4.5 模型支持,推出内置 Python 插件,并优化聊天列表导航与富文本编辑体验。
|
||||
|
||||
## 🌟 主要更新
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# ComfyUI Integration and Knowledge Base Improvements ⭐
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## 🌟 Key Updates
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# ComfyUI 集成与知识库优化 ⭐
|
||||
|
||||
LobeHub 在十月至十一月集成 ComfyUI 工作流,新增多个 AI 服务商与模型支持,并持续优化知识库与用户体验。
|
||||
LobeChat 在十月至十一月集成 ComfyUI 工作流,新增多个 AI 服务商与模型支持,并持续优化知识库与用户体验。
|
||||
|
||||
## 🌟 重要更新
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ tags:
|
||||
|
||||
# MCP Cloud Endpoints and Model Library Expansion 🔌
|
||||
|
||||
In November, LobeHub continued to improve model support and user experience by adding multiple AI providers and enhancing knowledge base capabilities.
|
||||
In November, LobeChat continued to improve model support and user experience by adding multiple AI providers and enhancing knowledge base capabilities.
|
||||
|
||||
## 🌟 Key Updates
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ tags:
|
||||
|
||||
# MCP 云端点与模型库扩展 🔌
|
||||
|
||||
LobeHub 在十一月持续优化模型支持与用户体验,新增多个 AI 服务商,并改进知识库功能。
|
||||
LobeChat 在十一月持续优化模型支持与用户体验,新增多个 AI 服务商,并改进知识库功能。
|
||||
|
||||
## 🌟 重要更新
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ tags:
|
||||
|
||||
LobeHub 使用 [Auth.js v5](https://authjs.dev/) 作为外部身份验证服务。Auth.js 是一个开源的身份验证库,它提供了一种简单的方式来实现身份验证和授权功能。本文档将介绍如何使用 Auth.js 来实现新的身份验证方式。
|
||||
|
||||
LobeHub 使用 [Better Auth](https://www.better-auth.com) 作为身份验证服务。本文档介绍如何添加新的 SSO 身份验证提供商。
|
||||
LobeChat 使用 [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/lobehub/discussions/7442)
|
||||
> 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)
|
||||
|
||||
## 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/lobehub/pull/8534)).
|
||||
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)).
|
||||
|
||||
**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/lobehub/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/lobe-chat/pull/8503)).
|
||||
|
||||
**Implementation Steps**:
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ tags:
|
||||
|
||||
# 添加新的图像模型
|
||||
|
||||
> 了解更多关于 AI 绘画模态的设计,请参考 [AI 绘画模态设计讨论](https://github.com/lobehub/lobehub/discussions/7442)
|
||||
> 了解更多关于 AI 绘画模态的设计,请参考 [AI 绘画模态设计讨论](https://github.com/lobehub/lobe-chat/discussions/7442)
|
||||
|
||||
## 参数标准化
|
||||
|
||||
@@ -63,7 +63,7 @@ const zhipuImageModels: AIImageModelCard[] = [
|
||||
|
||||
### 方式一:使用 OpenAI Compatible Factory
|
||||
|
||||
大部分 Provider 都使用 `openaiCompatibleFactory` 来兼容 OpenAI,可以通过传入自定义的 `createImage` 函数(参考 [PR #8534](https://github.com/lobehub/lobehub/pull/8534))。
|
||||
大部分 Provider 都使用 `openaiCompatibleFactory` 来兼容 OpenAI,可以通过传入自定义的 `createImage` 函数(参考 [PR #8534](https://github.com/lobehub/lobe-chat/pull/8534))。
|
||||
|
||||
**实现步骤**:
|
||||
|
||||
@@ -122,7 +122,7 @@ export const LobeProviderAI = openaiCompatibleFactory({
|
||||
|
||||
### 方式二:在 Provider 类中直接实现
|
||||
|
||||
如果你的 Provider 有独立的类实现,可以直接在类中添加 `createImage` 方法(参考 [PR #8503](https://github.com/lobehub/lobehub/pull/8503))。
|
||||
如果你的 Provider 有独立的类实现,可以直接在类中添加 `createImage` 方法(参考 [PR #8503](https://github.com/lobehub/lobe-chat/pull/8503))。
|
||||
|
||||
**实现步骤**:
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
---
|
||||
title: LobeHub API Client-Server Interaction Logic
|
||||
title: Lobe Chat API Client-Server Interaction Logic
|
||||
description: >-
|
||||
Explore the client-server interaction logic of LobeHub API, including event
|
||||
Explore the client-server interaction logic of Lobe Chat API, including event
|
||||
sequences.
|
||||
tags:
|
||||
- LobeHub API
|
||||
- Lobe Chat API
|
||||
- Client-Server Interaction
|
||||
- Event Sequences
|
||||
- API Logic
|
||||
---
|
||||
|
||||
# LobeHub API Client-Server Interaction Logic
|
||||
# Lobe Chat API Client-Server Interaction Logic
|
||||
|
||||
This document explains the implementation logic of LobeHub API in client-server interactions, including event sequences and core components involved.
|
||||
This document explains the implementation logic of Lobe Chat 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 LobeHub 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 Lobe Chat 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 LobeHub that encapsulates a unified
|
||||
|
||||
**Adapter Implementation Examples**:
|
||||
|
||||
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:
|
||||
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:
|
||||
|
||||
```ts
|
||||
// OpenRouter adapter implementation
|
||||
@@ -258,7 +258,7 @@ AgentRuntime is a core abstraction layer in LobeHub that encapsulates a unified
|
||||
apiKey: options.apiKey,
|
||||
baseURL: OPENROUTER_BASE_URL,
|
||||
defaultHeaders: {
|
||||
'HTTP-Referer': 'https://github.com/lobehub/lobehub',
|
||||
'HTTP-Referer': 'https://github.com/lobehub/lobe-chat',
|
||||
'X-Title': 'LobeHub',
|
||||
},
|
||||
});
|
||||
@@ -267,7 +267,7 @@ AgentRuntime is a core abstraction layer in LobeHub that encapsulates a unified
|
||||
|
||||
// Implement chat functionality
|
||||
async chat(payload: ChatCompletionCreateParamsBase, options?: RequestOptions) {
|
||||
// Convert LobeHub request format to OpenRouter format
|
||||
// Convert Lobe Chat 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 LobeHub that encapsulates a unified
|
||||
}
|
||||
```
|
||||
|
||||
2. **Google Gemini Adapter**: Gemini is Google's large language model. LobeHub supports Gemini series models through a dedicated adapter:
|
||||
2. **Google Gemini Adapter**: Gemini is Google's large language model. Lobe Chat supports Gemini series models through a dedicated adapter:
|
||||
|
||||
```ts
|
||||
import { GoogleGenerativeAI } from '@google/generative-ai';
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
---
|
||||
title: LobeHub API 前后端交互逻辑
|
||||
description: 深入了解 LobeHub API 的前后端交互实现逻辑和核心组件。
|
||||
title: Lobe Chat API 前后端交互逻辑
|
||||
description: 深入了解 Lobe Chat API 的前后端交互实现逻辑和核心组件。
|
||||
tags:
|
||||
- LobeHub API
|
||||
- Lobe Chat API
|
||||
- 前后端交互
|
||||
- 事件序列
|
||||
- 核心组件
|
||||
---
|
||||
|
||||
# LobeHub API 前后端交互逻辑
|
||||
# Lobe Chat API 前后端交互逻辑
|
||||
|
||||
本文档说明了 LobeHub API 在前后端交互中的实现逻辑,包括事件序列和涉及的核心组件。
|
||||
本文档说明了 Lobe Chat API 在前后端交互中的实现逻辑,包括事件序列和涉及的核心组件。
|
||||
|
||||
## 交互时序图
|
||||
|
||||
@@ -199,7 +199,7 @@ sequenceDiagram
|
||||
|
||||
## AgentRuntime 说明
|
||||
|
||||
AgentRuntime 是 LobeHub 中的一个核心抽象层,它封装了与不同 AI 模型提供商交互的统一接口。其主要职责和特点包括:
|
||||
AgentRuntime 是 Lobe Chat 中的一个核心抽象层,它封装了与不同 AI 模型提供商交互的统一接口。其主要职责和特点包括:
|
||||
|
||||
1. **统一抽象层**:AgentRuntime 提供了一个统一的接口,隐藏了不同 AI 提供商 API 的实现细节差异(如 OpenAI、Anthropic、Bedrock 等)。
|
||||
|
||||
@@ -242,7 +242,7 @@ AgentRuntime 是 LobeHub 中的一个核心抽象层,它封装了与不同 AI
|
||||
|
||||
**适配器实现示例**:
|
||||
|
||||
1. **OpenRouter 适配器**:OpenRouter 是一个统一 API,可以通过它访问多个模型提供商的 AI 模型。LobeHub 通过适配器实现对 OpenRouter 的支持:
|
||||
1. **OpenRouter 适配器**:OpenRouter 是一个统一 API,可以通过它访问多个模型提供商的 AI 模型。Lobe Chat 通过适配器实现对 OpenRouter 的支持:
|
||||
|
||||
```ts
|
||||
// OpenRouter 适配器实现
|
||||
@@ -256,7 +256,7 @@ AgentRuntime 是 LobeHub 中的一个核心抽象层,它封装了与不同 AI
|
||||
apiKey: options.apiKey,
|
||||
baseURL: OPENROUTER_BASE_URL,
|
||||
defaultHeaders: {
|
||||
'HTTP-Referer': 'https://github.com/lobehub/lobehub',
|
||||
'HTTP-Referer': 'https://github.com/lobehub/lobe-chat',
|
||||
'X-Title': 'LobeHub',
|
||||
},
|
||||
});
|
||||
@@ -265,7 +265,7 @@ AgentRuntime 是 LobeHub 中的一个核心抽象层,它封装了与不同 AI
|
||||
|
||||
// 实现聊天功能
|
||||
async chat(payload: ChatCompletionCreateParamsBase, options?: RequestOptions) {
|
||||
// 将 LobeHub 的请求格式转换为 OpenRouter 格式
|
||||
// 将 Lobe Chat 的请求格式转换为 OpenRouter 格式
|
||||
// 处理模型映射、消息格式等
|
||||
return this.client.chat.completions.create(
|
||||
{
|
||||
@@ -280,7 +280,7 @@ AgentRuntime 是 LobeHub 中的一个核心抽象层,它封装了与不同 AI
|
||||
}
|
||||
```
|
||||
|
||||
2. **Google Gemini 适配器**:Gemini 是 Google 的大语言模型,LobeHub 通过专门的适配器支持 Gemini 系列模型:
|
||||
2. **Google Gemini 适配器**:Gemini 是 Google 的大语言模型,Lobe Chat 通过专门的适配器支持 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/lobehub/discussions/891) as an example to illustrate the complete implementation process.
|
||||
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.
|
||||
|
||||
## 1. Update Schema
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
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).
|
||||
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).
|
||||
|
||||
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
|
||||
|
||||
lobehub is an internationalized project, so newly added text needs to update the default `locale` file: `src/locales/default/setting.ts`.
|
||||
lobe-chat 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/lobehub/discussions/891) 为例,阐述完整的实现流程。
|
||||
我们将以 [RFC 021 - 自定义助手开场引导](https://github.com/lobehub/lobe-chat/discussions/891) 为例,阐述完整的实现流程。
|
||||
|
||||
## 一、更新 schema
|
||||
|
||||
lobehub 使用 postgres 数据库,浏览器端本地数据库使用 [pglite](https://pglite.dev/)(wasm 版本 postgres)。项目还使用了 [drizzle](https://orm.drizzle.team/) ORM 用来操作数据库。
|
||||
lobe-chat 使用 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 实现
|
||||
|
||||
lobehub 使用 [zustand](https://zustand.docs.pmnd.rs/getting-started/introduction) 作为全局状态管理框架,对于状态管理的详细实践介绍,可以查阅 [📘 状态管理最佳实践](/zh/docs/development/state-management/state-management-intro)。
|
||||
lobe-chat 使用 [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 框架和多语言自动翻译工具
|
||||
|
||||
lobehub 是个国际化项目,新加的文案需要更新默认的 `locale` 文件: `src/locales/default/setting.ts` 。
|
||||
lobe-chat 是个国际化项目,新加的文案需要更新默认的 `locale` 文件: `src/locales/default/setting.ts` 。
|
||||
|
||||
我们以子组件 `OpeningQuestion.tsx` 为例,组件实现:
|
||||
|
||||
|
||||
@@ -17,29 +17,20 @@ The directory structure of LobeHub is as follows:
|
||||
|
||||
```bash
|
||||
src
|
||||
├── 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 # 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
|
||||
|
||||
@@ -15,29 +15,20 @@ LobeHub 的文件夹目录架构如下:
|
||||
|
||||
```bash
|
||||
src
|
||||
├── 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 # 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
|
||||
|
||||
@@ -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/lobehub/blob/main/.vscode/extensions.json) for the best development experience.
|
||||
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.
|
||||
|
||||
### 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/lobehub.git
|
||||
git clone https://github.com/lobehub/lobe-chat.git
|
||||
```
|
||||
|
||||
2. **Install dependencies**: Then, navigate to the project directory and use PNPM to install the project's dependencies:
|
||||
|
||||
```bash
|
||||
cd lobehub
|
||||
cd lobe-chat
|
||||
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/lobehub
|
||||
[codespaces-link]: https://codespaces.new/lobehub/lobe-chat
|
||||
[codespaces-shield]: https://github.com/codespaces/badge.svg
|
||||
|
||||
@@ -35,7 +35,7 @@ tags:
|
||||
|
||||
### VSCode 用户
|
||||
|
||||
推荐安装 [.vscode/extensions.json](https://github.com/lobehub/lobehub/blob/main/.vscode/extensions.json) 中推荐安装的扩展获得最佳开发体验。
|
||||
推荐安装 [.vscode/extensions.json](https://github.com/lobehub/lobe-chat/blob/main/.vscode/extensions.json) 中推荐安装的扩展获得最佳开发体验。
|
||||
|
||||
### 项目设置
|
||||
|
||||
@@ -44,13 +44,13 @@ tags:
|
||||
1. **获取代码**:首先,你需要从 GitHub 上克隆 LobeHub 的代码库。在终端中运行以下命令:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/lobehub/lobehub.git
|
||||
git clone https://github.com/lobehub/lobe-chat.git
|
||||
```
|
||||
|
||||
2. **安装依赖**:然后,进入项目目录,并使用 `pnpm` 安装项目的依赖包:
|
||||
|
||||
```bash
|
||||
cd lobehub
|
||||
cd lobe-chat
|
||||
pnpm i
|
||||
```
|
||||
|
||||
@@ -78,5 +78,5 @@ bun run dev
|
||||
|
||||
在开发过程中,如果你在环境设置上遇到任何问题,或者有任何关于 LobeHub 开发的问题,欢迎随时向我们提问。我们期待看到你的贡献!
|
||||
|
||||
[codespaces-link]: https://codespaces.new/lobehub/lobehub
|
||||
[codespaces-link]: https://codespaces.new/lobehub/lobe-chat
|
||||
[codespaces-shield]: https://github.com/codespaces/badge.svg
|
||||
|
||||
@@ -101,6 +101,7 @@ 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,6 +101,7 @@ 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/lobehub/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/lobe-chat/pull/759).
|
||||
|
||||
### Additional Information
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ npm run i18n
|
||||
|
||||
一旦你完成了上述步骤,你需要提交你的更改并创建一个 Pull Request。
|
||||
|
||||
请确保你遵循了 LobeHub 的贡献指南,并提供必要的描述来说明你的更改。例如,参考之前的类似 Pull Request [#759](https://github.com/lobehub/lobehub/pull/759)。
|
||||
请确保你遵循了 LobeHub 的贡献指南,并提供必要的描述来说明你的更改。例如,参考之前的类似 Pull Request [#759](https://github.com/lobehub/lobe-chat/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/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)
|
||||
- [✨ 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)
|
||||
|
||||
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/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)
|
||||
- [✨ 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)
|
||||
|
||||
要添加新的语种支持, 详细步骤请参考:[新语种添加指南](/zh/docs/development/internationalization/add-new-locale)。
|
||||
|
||||
|
||||
@@ -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/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
|
||||
[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
|
||||
|
||||
@@ -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/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
|
||||
[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
|
||||
|
||||
+15
-22
@@ -34,25 +34,18 @@ The folder directory structure of LobeHub is as follows:
|
||||
|
||||
```bash
|
||||
src
|
||||
├── 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
|
||||
├── 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
|
||||
```
|
||||
|
||||
For a detailed introduction to the directory structure, see: [Folder Directory Structure](/docs/development/basic/folder-structure)
|
||||
@@ -66,13 +59,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/lobehub.git
|
||||
git clone https://github.com/lobehub/lobe-chat.git
|
||||
```
|
||||
|
||||
2. **Install dependencies**: Enter the project directory and install the required dependencies:
|
||||
|
||||
```bash
|
||||
cd lobehub
|
||||
cd lobe-chat
|
||||
# If you use Bun
|
||||
bun install
|
||||
# If you use PNPM
|
||||
@@ -117,6 +110,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/lobehub/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/lobe-chat/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.
|
||||
|
||||
@@ -32,25 +32,18 @@ LobeHub 的文件夹目录架构如下:
|
||||
|
||||
```bash
|
||||
src
|
||||
├── 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 # 通用的工具函数
|
||||
├── app # 应用主要逻辑和状态管理相关的代码
|
||||
├── components # 可复用的 UI 组件
|
||||
├── config # 应用的配置文件,包含客户端环境变量与服务端环境变量
|
||||
├── const # 用于定义常量,如 action 类型、路由名等
|
||||
├── features # 与业务功能相关的功能模块,如 Agent 设置、插件开发弹窗等
|
||||
├── hooks # 全应用复用自定义的工具 Hooks
|
||||
├── layout # 应用的布局组件,如导航栏、侧边栏等
|
||||
├── locales # 国际化的语言文件
|
||||
├── services # 封装的后端服务接口,如 HTTP 请求
|
||||
├── store # 用于状态管理的 zustand store
|
||||
├── types # TypeScript 的类型定义文件
|
||||
└── utils # 通用的工具函数
|
||||
```
|
||||
|
||||
有关目录架构的详细介绍,详见: [文件夹目录架构](/zh/docs/development/basic/folder-structure)
|
||||
@@ -64,13 +57,13 @@ src
|
||||
1. **获取代码**:克隆 LobeHub 的代码库到本地:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/lobehub/lobehub.git
|
||||
git clone https://github.com/lobehub/lobe-chat.git
|
||||
```
|
||||
|
||||
2. **安装依赖**:进入项目目录,并安装所需依赖:
|
||||
|
||||
```bash
|
||||
cd lobehub
|
||||
cd lobe-chat
|
||||
# 如果你使用 Bun
|
||||
bun install
|
||||
# 如果你使用 PNPM
|
||||
@@ -115,6 +108,6 @@ LobeHub 采用 `i18next` 和 `lobe-i18n` 实现多语言支持,确保用户全
|
||||
|
||||
为了支持开发者更好地理解和使用 LobeHub 的技术栈,我们提供了一份详尽的资源与参考列表 —— [LobeHub 资源与参考](/zh/docs/development/basic/resources) - 访问我们维护的资源列表,包括教程、文章和其他有用的链接。
|
||||
|
||||
我们鼓励开发者利用这些资源深入学习和提升技能,通过 [LobeHub GitHub Discussions](https://github.com/lobehub/lobehub/discussions) 或者 [Discord](https://discord.com/invite/AYFPHvv2jT) 加入社区讨论,提出问题或分享你的经验。
|
||||
我们鼓励开发者利用这些资源深入学习和提升技能,通过 [LobeHub GitHub Discussions](https://github.com/lobehub/lobe-chat/discussions) 或者 [Discord](https://discord.com/invite/AYFPHvv2jT) 加入社区讨论,提出问题或分享你的经验。
|
||||
|
||||
如果你有任何疑问,或者需要进一步的帮助,请不要犹豫,请通过上述渠道与我们联系。
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
title: LobeHub Authentication Service Configuration
|
||||
description: >-
|
||||
Learn how to configure external authentication services using Better Auth
|
||||
for centralized user authorization management. Supported
|
||||
Learn how to configure external authentication services using Better Auth,
|
||||
Clerk, or Next Auth for centralized user authorization management. Supported
|
||||
authentication services include Auth0, Azure ID, etc.
|
||||
tags:
|
||||
- Authentication Service
|
||||
@@ -12,7 +12,17 @@ tags:
|
||||
|
||||
# Authentication Service
|
||||
|
||||
LobeHub supports the configuration of external authentication services using Better Auth for internal use within enterprises/organizations to centrally manage user authorization.
|
||||
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.
|
||||
|
||||
## Better Auth
|
||||
|
||||
@@ -30,11 +40,12 @@ LobeHub supports the configuration of external authentication services using Bet
|
||||
|
||||
To enable Better Auth in LobeHub, set the following environment variables:
|
||||
|
||||
| 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` |
|
||||
| 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` |
|
||||
|
||||
## Supported SSO Providers
|
||||
|
||||
@@ -61,8 +72,6 @@ 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'} />
|
||||
@@ -107,7 +116,63 @@ When configuring OAuth providers, use the following callback URL format:
|
||||
|
||||
## Email Service Configuration
|
||||
|
||||
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).
|
||||
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) |
|
||||
|
||||
<Callout type={'tip'}>
|
||||
Go to [Environment Variables](/docs/self-hosting/environment-variables/auth#better-auth) for detailed information on all Better Auth variables.
|
||||
@@ -151,16 +216,6 @@ 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:
|
||||
@@ -178,8 +233,10 @@ 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.
|
||||
|
||||
### Other SSO Providers
|
||||
### 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.
|
||||
Allow the session store in database, see also the [Auth.js Session Documentation](https://authjs.dev/concepts/session-strategies#database-session).
|
||||
|
||||
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).
|
||||
## 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.
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: LobeHub 身份验证服务配置
|
||||
description: >-
|
||||
了解如何使用 Better Auth 配置外部身份验证服务,以统一管理用户授权。支持的身份验证服务包括 Auth0、
|
||||
了解如何使用 Better Auth、Clerk 或 Next Auth 配置外部身份验证服务,以统一管理用户授权。支持的身份验证服务包括 Auth0、
|
||||
Azure ID 等。
|
||||
tags:
|
||||
- 身份验证服务
|
||||
@@ -12,7 +12,17 @@ tags:
|
||||
|
||||
# 身份验证服务
|
||||
|
||||
LobeHub 支持使用 Better Auth 配置外部身份验证服务,供企业 / 组织内部使用,统一管理用户授权。
|
||||
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。
|
||||
|
||||
## Better Auth
|
||||
|
||||
@@ -30,11 +40,12 @@ LobeHub 支持使用 Better Auth 配置外部身份验证服务,供企业 /
|
||||
|
||||
要在 LobeHub 中启用 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` |
|
||||
| 环境变量 | 类型 | 描述 |
|
||||
| -------------------------------- | -- | --------------------------------------------------------------------------------------------------------------- |
|
||||
| `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` |
|
||||
|
||||
## 支持的 SSO 提供商
|
||||
|
||||
@@ -61,8 +72,6 @@ LobeHub 支持使用 Better Auth 配置外部身份验证服务,供企业 /
|
||||
点击下方提供商查看详细配置指南:
|
||||
|
||||
<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'} />
|
||||
@@ -107,7 +116,63 @@ LobeHub 支持使用 Better Auth 配置外部身份验证服务,供企业 /
|
||||
|
||||
## 邮件服务配置
|
||||
|
||||
邮件服务用于邮箱验证、密码重置和魔法链接发送。详细配置请参阅 [邮件服务配置](/zh/docs/self-hosting/auth/email)。
|
||||
用于邮箱验证、密码重置和魔法链接发送。支持两种邮件服务:
|
||||
|
||||
### 方式一:Nodemailer(SMTP)
|
||||
|
||||
使用 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` 以启用魔法链接登录(默认关闭) |
|
||||
|
||||
<Callout type={'tip'}>
|
||||
前往 [环境变量](/zh/docs/self-hosting/environment-variables/auth#better-auth) 可查阅所有 Better Auth 相关变量详情。
|
||||
@@ -152,16 +217,6 @@ 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` 环境变量,支持完整邮箱地址或域名,以逗号分隔。例如:
|
||||
@@ -177,8 +232,10 @@ Better Auth 支持内置提供商(Google、GitHub、Microsoft、Apple、AWS Co
|
||||
|
||||
允许 LobeHub 在身份提供商中用户信息更新时接收通知。支持的提供商包括 Casdoor 和 Logto。请参考具体提供商文档进行配置。
|
||||
|
||||
### 其他 SSO 提供商
|
||||
### 数据库会话
|
||||
|
||||
如果你需要使用上述列表中未包含的 SSO 提供商,可以使用 [Generic OIDC](/zh/docs/self-hosting/auth/providers/generic-oidc) 来配置任何符合 OpenID Connect 或 OAuth 2.0 标准的提供商。
|
||||
允许会话存储在数据库中,详情请参阅 [Auth.js 会话文档](https://authjs.dev/concepts/session-strategies#database-session)。
|
||||
|
||||
欢迎提交 Pull Request 来添加更多内置 SSO 提供商支持。详情请参考 [Better Auth 文档](https://www.better-auth.com/docs/concepts/oauth)。
|
||||
## 其他 SSO 提供商
|
||||
|
||||
请参考 [Auth.js](https://authjs.dev/getting-started/authentication/oauth) 文档,欢迎提交 Pull Request。
|
||||
+7
-7
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Migrating from Clerk to Better Auth
|
||||
description: >-
|
||||
Guide for migrating your LobeHub deployment from Clerk authentication to
|
||||
Guide for migrating your LobeChat deployment from Clerk authentication to
|
||||
Better Auth, including simple and full migration options.
|
||||
tags:
|
||||
- Authentication Service
|
||||
@@ -12,17 +12,17 @@ tags:
|
||||
|
||||
# Migrating from Clerk to Better Auth
|
||||
|
||||
This guide helps you migrate your existing Clerk-based LobeHub deployment to Better Auth.
|
||||
This guide helps you migrate your existing Clerk-based LobeChat deployment to Better Auth.
|
||||
|
||||
<Callout type={'info'}>
|
||||
Better Auth is the recommended authentication solution for LobeHub. It offers simpler configuration, more SSO providers, and better self-hosting support.
|
||||
Better Auth is the recommended authentication solution for LobeChat. It offers simpler configuration, more SSO providers, and better self-hosting support.
|
||||
</Callout>
|
||||
|
||||
<Callout type={'error'}>
|
||||
**Important Notice**:
|
||||
|
||||
- **Always backup your database first!** For Neon users, create a backup via [Fork Branch](https://neon.tech/docs/manage/branches#create-a-branch)
|
||||
- LobeHub is not responsible for any data loss or issues that may occur during the migration process
|
||||
- LobeChat is not responsible for any data loss or issues that may occur during the migration process
|
||||
- This guide is intended for users with development experience; not recommended for users without technical background
|
||||
- If you have any questions, feel free to ask in our [Discord](https://discord.com/invite/AYFPHvv2jT) community or [GitHub Issue](https://github.com/lobehub/lobe-chat/issues/11707)
|
||||
</Callout>
|
||||
@@ -83,7 +83,7 @@ For small self-hosted deployments, the simplest approach is to let users reset t
|
||||
See [Authentication Service Configuration](/docs/self-hosting/advanced/auth) for complete environment variables and SSO provider setup.
|
||||
</Callout>
|
||||
|
||||
3. **Redeploy LobeHub**
|
||||
3. **Redeploy LobeChat**
|
||||
|
||||
Deploy the new version with Better Auth enabled.
|
||||
|
||||
@@ -102,7 +102,7 @@ For small self-hosted deployments, the simplest approach is to let users reset t
|
||||
- Log in using their previously linked social account (e.g., Google, GitHub)
|
||||
- Click "Set Password" to receive an email and set a new password
|
||||
|
||||

|
||||

|
||||
|
||||
3. (Optional) After logging in, users can manage their account in the Profile page:
|
||||
- Linked Accounts: Link additional social accounts
|
||||
@@ -139,7 +139,7 @@ For larger deployments or when you need to preserve user passwords and SSO conne
|
||||
|
||||
**Preparation:**
|
||||
|
||||
1. Clone the LobeHub repository and install dependencies:
|
||||
1. Clone the LobeChat repository and install dependencies:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/lobehub/lobe-chat.git
|
||||
+7
-7
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: 从 Clerk 迁移到 Better Auth
|
||||
description: 将 LobeHub 部署从 Clerk 身份验证迁移到 Better Auth 的指南,包括简单迁移和完整迁移选项。
|
||||
description: 将 LobeChat 部署从 Clerk 身份验证迁移到 Better Auth 的指南,包括简单迁移和完整迁移选项。
|
||||
tags:
|
||||
- 身份验证服务
|
||||
- Better Auth
|
||||
@@ -10,17 +10,17 @@ tags:
|
||||
|
||||
# 从 Clerk 迁移到 Better Auth
|
||||
|
||||
本指南帮助您将现有的基于 Clerk 的 LobeHub 部署迁移到 Better Auth。
|
||||
本指南帮助您将现有的基于 Clerk 的 LobeChat 部署迁移到 Better Auth。
|
||||
|
||||
<Callout type={'info'}>
|
||||
Better Auth 是 LobeHub 推荐的身份验证解决方案。它提供更简单的配置、更多的 SSO 提供商支持,以及更好的自托管体验。
|
||||
Better Auth 是 LobeChat 推荐的身份验证解决方案。它提供更简单的配置、更多的 SSO 提供商支持,以及更好的自托管体验。
|
||||
</Callout>
|
||||
|
||||
<Callout type={'error'}>
|
||||
**重要提醒**:
|
||||
|
||||
- **务必先备份数据库**!如使用 Neon,可通过 [Fork 分支](https://neon.tech/docs/manage/branches#create-a-branch) 创建备份
|
||||
- 迁移过程中可能出现的任何数据丢失或问题,LobeHub 概不负责
|
||||
- 迁移过程中可能出现的任何数据丢失或问题,LobeChat 概不负责
|
||||
- 本指南适合有一定开发背景的用户,不建议无技术经验的用户自行操作
|
||||
- 如有任何疑问,欢迎到 [Discord](https://discord.com/invite/AYFPHvv2jT) 社区或 [GitHub Issue](https://github.com/lobehub/lobe-chat/issues/11707) 提问
|
||||
</Callout>
|
||||
@@ -81,7 +81,7 @@ tags:
|
||||
查阅 [身份验证服务配置](/zh/docs/self-hosting/advanced/auth) 了解完整的环境变量和 SSO 提供商配置。
|
||||
</Callout>
|
||||
|
||||
3. **重新部署 LobeHub**
|
||||
3. **重新部署 LobeChat**
|
||||
|
||||
部署启用 Better Auth 的新版本。
|
||||
|
||||
@@ -99,7 +99,7 @@ tags:
|
||||
- 使用之前关联的社交账号(如 Google、GitHub)登录
|
||||
- 点击「设置密码」链接,通过邮件设置新密码后登录
|
||||
|
||||

|
||||

|
||||
|
||||
3. (可选)登录后可在个人资料页进行以下操作:
|
||||
- 已关联账号:手动关联其他社交账号
|
||||
@@ -134,7 +134,7 @@ tags:
|
||||
|
||||
**准备工作:**
|
||||
|
||||
1. Clone LobeHub 仓库并安装依赖:
|
||||
1. Clone LobeChat 仓库并安装依赖:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/lobehub/lobe-chat.git
|
||||
@@ -22,9 +22,9 @@ This page documents the legacy authentication methods (NextAuth and Clerk) for u
|
||||
|
||||
Clerk is a comprehensive identity verification solution that provides a simple yet powerful API and services to handle user authentication and session management.
|
||||
|
||||
LobeHub has deeply integrated with Clerk to provide users with a secure and convenient login and registration experience.
|
||||
LobeChat has deeply integrated with Clerk to provide users with a secure and convenient login and registration experience.
|
||||
|
||||
By setting the environment variables `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` and `CLERK_SECRET_KEY` in LobeHub's environment, you can enable and use Clerk.
|
||||
By setting the environment variables `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` and `CLERK_SECRET_KEY` in LobeChat's environment, you can enable and use Clerk.
|
||||
|
||||
<Callout type={'info'}>
|
||||
For detailed Clerk configuration, see [Clerk Configuration Guide](/docs/self-hosting/advanced/auth/clerk).
|
||||
@@ -40,15 +40,15 @@ By setting the environment variables `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` and `CL
|
||||
To migrate from NextAuth to Better Auth, see the [NextAuth Migration Guide](/docs/self-hosting/advanced/auth/nextauth-to-betterauth).
|
||||
</Callout>
|
||||
|
||||
Before using NextAuth, please set the following variables in LobeHub's environment variables:
|
||||
Before using NextAuth, please set the following variables in LobeChat's environment variables:
|
||||
|
||||
| Environment Variable | Type | Description |
|
||||
| -------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Environment Variable | Type | Description |
|
||||
| -------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `NEXT_PUBLIC_ENABLE_NEXT_AUTH` | Required | This is used to enable the NextAuth service. Set it to `1` to enable it; changing this setting requires recompiling the application. Users deploying with the `lobehub/lobehub` image have this configuration added by default. |
|
||||
| `AUTH_SECRET` | Required | The key used to encrypt Auth.js session tokens. You can use the following command: `openssl rand -base64 32`, or visit `https://generate-secret.vercel.app/32` to generate the key. |
|
||||
| `AUTH_URL` | Required | This URL specifies the callback address for Auth.js when performing OAuth verification. Set this only if the default generated redirect address is incorrect. `https://example.com/api/auth` |
|
||||
| `NEXT_AUTH_SSO_PROVIDERS` | Optional | This environment variable is used to enable multiple identity verification sources simultaneously, separated by commas, for example, `auth0,microsoft-entra-id,authentik`. |
|
||||
| `NEXT_AUTH_SSO_SESSION_STRATEGY` | Optional | The session strategy for Auth.js. Options are `jwt` or `database`. Default is `jwt`. |
|
||||
| `AUTH_SECRET` | Required | The key used to encrypt Auth.js session tokens. You can use the following command: `openssl rand -base64 32`, or visit `https://generate-secret.vercel.app/32` to generate the key. |
|
||||
| `AUTH_URL` | Required | This URL specifies the callback address for Auth.js when performing OAuth verification. Set this only if the default generated redirect address is incorrect. `https://example.com/api/auth` |
|
||||
| `NEXT_AUTH_SSO_PROVIDERS` | Optional | This environment variable is used to enable multiple identity verification sources simultaneously, separated by commas, for example, `auth0,microsoft-entra-id,authentik`. |
|
||||
| `NEXT_AUTH_SSO_SESSION_STRATEGY` | Optional | The session strategy for Auth.js. Options are `jwt` or `database`. Default is `jwt`. |
|
||||
|
||||
Currently supported identity verification services include:
|
||||
|
||||
@@ -103,7 +103,7 @@ The order corresponds to the display order of the SSO providers.
|
||||
|
||||
### Webhook Support
|
||||
|
||||
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.
|
||||
Allow LobeChat 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
|
||||
|
||||
+5
-5
@@ -20,9 +20,9 @@ tags:
|
||||
|
||||
Clerk 是一个全面的身份验证解决方案,它提供了简单而强大的 API 和服务来处理用户认证和会话管理。
|
||||
|
||||
LobeHub 与 Clerk 做了深度集成,能够为用户提供安全、便捷的登录和注册体验。
|
||||
LobeChat 与 Clerk 做了深度集成,能够为用户提供安全、便捷的登录和注册体验。
|
||||
|
||||
在 LobeHub 的环境变量中设置 `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` 和 `CLERK_SECRET_KEY`,即可开启和使用 Clerk。
|
||||
在 LobeChat 的环境变量中设置 `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` 和 `CLERK_SECRET_KEY`,即可开启和使用 Clerk。
|
||||
|
||||
<Callout type={'info'}>
|
||||
详细的 Clerk 配置请参阅 [Clerk 配置指南](/zh/docs/self-hosting/advanced/auth/clerk)。
|
||||
@@ -38,11 +38,11 @@ LobeHub 与 Clerk 做了深度集成,能够为用户提供安全、便捷的
|
||||
如需从 NextAuth 迁移到 Better Auth,请参阅 [NextAuth 迁移指南](/zh/docs/self-hosting/advanced/auth/nextauth-to-betterauth)。
|
||||
</Callout>
|
||||
|
||||
在使用 NextAuth 之前,请先在 LobeHub 的环境变量中设置以下变量:
|
||||
在使用 NextAuth 之前,请先在 LobeChat 的环境变量中设置以下变量:
|
||||
|
||||
| 环境变量 | 类型 | 描述 |
|
||||
| -------------------------------- | -- | ------------------------------------------------------------------------------------------------------------ |
|
||||
| `NEXT_PUBLIC_ENABLE_NEXT_AUTH` | 必选 | 用于启用 NextAuth 服务,设置为 `1` 以启用,更改此项需要重新编译应用。使用 `lobehub/lobehub` 镜像部署的用户已经默认添加了该项配置。 |
|
||||
| `NEXT_PUBLIC_ENABLE_NEXT_AUTH` | 必选 | 用于启用 NextAuth 服务,设置为 `1` 以启用,更改此项需要重新编译应用。使用 `lobehub/lobehub` 镜像部署的用户已经默认添加了该项配置。 |
|
||||
| `NEXT_AUTH_SECRET` | 必选 | 用于加密 Auth.js 会话令牌的密钥。您可以使用以下命令: `openssl rand -base64 32`,或者访问 `https://generate-secret.vercel.app/32` 生成秘钥。 |
|
||||
| `AUTH_URL` | 必选 | 该 URL 用于指定 Auth.js 在执行 OAuth 验证时的回调地址,当默认生成的重定向地址发生不正确时才需要设置。`https://example.com/api/auth` |
|
||||
| `NEXT_AUTH_SSO_PROVIDERS` | 可选 | 该环境变量用于同时启用多个身份验证源,以逗号 `,` 分割,例如 `auth0,microsoft-entra-id,authentik`。 |
|
||||
@@ -98,7 +98,7 @@ LobeHub 与 Clerk 做了深度集成,能够为用户提供安全、便捷的
|
||||
|
||||
### Webhook 支持
|
||||
|
||||
允许 LobeHub 在身份提供商中用户信息更新时接收通知。支持的提供商包括 Casdoor 和 Logto。请参考具体提供商文档进行配置。
|
||||
允许 LobeChat 在身份提供商中用户信息更新时接收通知。支持的提供商包括 Casdoor 和 Logto。请参考具体提供商文档进行配置。
|
||||
|
||||
### 数据库会话
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Understanding Auth Migration - Technical Deep Dive
|
||||
description: >-
|
||||
Technical explanation of how authentication migration works in LobeHub,
|
||||
Technical explanation of how authentication migration works in LobeChat,
|
||||
including database schema, migration principles, and troubleshooting guide.
|
||||
tags:
|
||||
- Authentication
|
||||
@@ -12,7 +12,7 @@ tags:
|
||||
|
||||
# Understanding Auth Migration
|
||||
|
||||
This document explains the technical principles behind authentication migration in LobeHub. It's intended for users with database and development experience who want to understand how migration works under the hood.
|
||||
This document explains the technical principles behind authentication migration in LobeChat. It's intended for users with database and development experience who want to understand how migration works under the hood.
|
||||
|
||||
<Callout type={'info'}>
|
||||
For step-by-step migration instructions, see [NextAuth Migration](/docs/self-hosting/advanced/auth/nextauth-to-betterauth) or [Clerk Migration](/docs/self-hosting/advanced/auth/clerk-to-betterauth).
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 认证迁移原理 - 技术深入解析
|
||||
description: >-
|
||||
LobeHub 认证迁移的技术原理解析,包括数据库 Schema、迁移原理和问题排查指南。
|
||||
LobeChat 认证迁移的技术原理解析,包括数据库 Schema、迁移原理和问题排查指南。
|
||||
tags:
|
||||
- 认证
|
||||
- 迁移
|
||||
@@ -11,7 +11,7 @@ tags:
|
||||
|
||||
# 认证迁移原理
|
||||
|
||||
本文档解释 LobeHub 认证迁移的技术原理,适合有数据库和开发经验的用户,帮助理解迁移的底层逻辑。
|
||||
本文档解释 LobeChat 认证迁移的技术原理,适合有数据库和开发经验的用户,帮助理解迁移的底层逻辑。
|
||||
|
||||
<Callout type={'info'}>
|
||||
如需分步迁移指南,请参阅 [NextAuth 迁移](/docs/self-hosting/advanced/auth/nextauth-to-betterauth) 或 [Clerk 迁移](/docs/self-hosting/advanced/auth/clerk-to-betterauth)。
|
||||
+3
-3
@@ -13,7 +13,7 @@ tags:
|
||||
[Casdoor](https://github.com/casdoor/casdoor) 是一个开源的身份验证服务,功能配置丰富且易于上手。
|
||||
|
||||
<Callout type={'tip'}>
|
||||
若你想要私有部署 Casdoor,我们建议你将之与 LobeHub 一同使用 Docker Compose 部署,此时
|
||||
若你想要私有部署 Casdoor,我们建议你将之与 LobeHub 数据库版本一同使用 Docker Compose 部署,此时
|
||||
LobeHub 可以与之共用同一个 Postgres 实例。
|
||||
</Callout>
|
||||
|
||||
@@ -21,12 +21,12 @@ tags:
|
||||
|
||||
若你使用局域网 IP 部署,下文假设:
|
||||
|
||||
- 你的 LobeHub IP / 端口为 `http://LobeHub_IP:3210`。
|
||||
- 你的 LobeHub 数据库版本 IP / 端口为 `http://LobeHub_IP:3210`。
|
||||
- 你私有部署 Casdoor,其域名为 `http://CASDOOR_IP:8000`。
|
||||
|
||||
若你使用公网部署,下文假设:
|
||||
|
||||
- 你的 LobeHub 域名为 `https://lobe.example.com`。
|
||||
- 你的 LobeHub 数据库版本域名为 `https://lobe.example.com`。
|
||||
- 你私有部署 Casdoor,其域名为 `https://lobe-auth-api.example.com`。
|
||||
|
||||
<Steps>
|
||||
+2
-2
@@ -21,12 +21,12 @@ tags:
|
||||
|
||||
若你使用局域网 IP 部署,下文假设:
|
||||
|
||||
- 你的 LobeHub IP / 端口为 `http://LobeHub_IP:3210`。
|
||||
- 你的 LobeHub 数据库版本 IP / 端口为 `http://LobeHub_IP:3210`。
|
||||
- 你私有部署 Keycloak,其域名为 `http://KEYCLOAK_IP:8080`。
|
||||
|
||||
若你使用公网部署,下文假设:
|
||||
|
||||
- 你的 LobeHub 域名为 `https://lobe.example.com`。
|
||||
- 你的 LobeHub 数据库版本域名为 `https://lobe.example.com`。
|
||||
- 你私有部署 Keycloak,其域名为 `https://lobe-auth-api.example.com`。
|
||||
|
||||
<Steps>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user