@lobehub/lobehub 2.0.0-next.153 → 2.0.0-next.155
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/changelog/v1.json +18 -0
- package/locales/ar/discover.json +2 -0
- package/locales/bg-BG/discover.json +2 -0
- package/locales/de-DE/discover.json +2 -0
- package/locales/en-US/discover.json +2 -0
- package/locales/es-ES/discover.json +2 -0
- package/locales/fa-IR/discover.json +2 -0
- package/locales/fr-FR/discover.json +2 -0
- package/locales/it-IT/discover.json +2 -0
- package/locales/ja-JP/discover.json +2 -0
- package/locales/ko-KR/discover.json +2 -0
- package/locales/nl-NL/discover.json +2 -0
- package/locales/pl-PL/discover.json +2 -0
- package/locales/pt-BR/discover.json +2 -0
- package/locales/ru-RU/discover.json +2 -0
- package/locales/tr-TR/discover.json +2 -0
- package/locales/vi-VN/discover.json +2 -0
- package/locales/zh-CN/discover.json +2 -0
- package/locales/zh-TW/discover.json +2 -0
- package/package.json +1 -1
- package/packages/python-interpreter/src/types.ts +2 -2
- package/packages/types/src/discover/plugins.ts +12 -0
- package/src/app/[variants]/(main)/discover/(detail)/assistant/features/Details/Capabilities/PluginItem.tsx +109 -13
- package/src/app/[variants]/(main)/discover/(detail)/assistant/features/Details/Capabilities/Plugins.tsx +1 -7
- package/src/app/[variants]/(main)/discover/(list)/(home)/Client.tsx +2 -2
- package/src/app/[variants]/(main)/discover/(list)/(home)/index.tsx +2 -3
- package/src/app/[variants]/(main)/discover/features/Title.tsx +2 -1
- package/src/auth.ts +21 -0
- package/src/locales/default/discover.ts +2 -0
- package/src/server/services/discover/index.ts +95 -73
- package/src/server/services/user/index.ts +35 -22
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 2.0.0-next.155](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.154...v2.0.0-next.155)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2025-12-03**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: Missing init user after user creation.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: Missing init user after user creation, closes [#10587](https://github.com/lobehub/lobe-chat/issues/10587) ([0e97a42](https://github.com/lobehub/lobe-chat/commit/0e97a42))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## [Version 2.0.0-next.154](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.153...v2.0.0-next.154)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2025-12-03**</sup>
|
|
33
|
+
|
|
34
|
+
#### 🐛 Bug Fixes
|
|
35
|
+
|
|
36
|
+
- **misc**: Udpate discover detail tools get & more link.
|
|
37
|
+
|
|
38
|
+
<br/>
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
42
|
+
|
|
43
|
+
#### What's fixed
|
|
44
|
+
|
|
45
|
+
- **misc**: Udpate discover detail tools get & more link, closes [#10586](https://github.com/lobehub/lobe-chat/issues/10586) ([8ace3f0](https://github.com/lobehub/lobe-chat/commit/8ace3f0))
|
|
46
|
+
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
<div align="right">
|
|
50
|
+
|
|
51
|
+
[](#readme-top)
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
5
55
|
## [Version 2.0.0-next.153](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.152...v2.0.0-next.153)
|
|
6
56
|
|
|
7
57
|
<sup>Released on **2025-12-03**</sup>
|
package/changelog/v1.json
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"children": {
|
|
4
|
+
"fixes": [
|
|
5
|
+
"Missing init user after user creation."
|
|
6
|
+
]
|
|
7
|
+
},
|
|
8
|
+
"date": "2025-12-03",
|
|
9
|
+
"version": "2.0.0-next.155"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"children": {
|
|
13
|
+
"fixes": [
|
|
14
|
+
"Udpate discover detail tools get & more link."
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"date": "2025-12-03",
|
|
18
|
+
"version": "2.0.0-next.154"
|
|
19
|
+
},
|
|
2
20
|
{
|
|
3
21
|
"children": {},
|
|
4
22
|
"date": "2025-12-03",
|
package/locales/ar/discover.json
CHANGED
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "مزودو الخدمة المدعومون لهذا النموذج"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "الملحقات المدمجة",
|
|
619
620
|
"community": "إضافات المجتمع",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "تثبيت الإضافة",
|
|
632
633
|
"installed": "تم التثبيت",
|
|
634
|
+
"legacyTag": "الملحقات القديمة",
|
|
633
635
|
"list": "قائمة الإضافات",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "وصف",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "Доставчици, поддържащи този модел"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "Вграден плъгин",
|
|
619
620
|
"community": "Обществени плъгини",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "Инсталирай плъгин",
|
|
632
633
|
"installed": "Инсталиран",
|
|
634
|
+
"legacyTag": "Остарял плъгин",
|
|
633
635
|
"list": "Списък с плъгини",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "Описание",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "Anbieter, die dieses Modell unterstützen"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "Integriertes Plugin",
|
|
619
620
|
"community": "Community-Plugins",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "Plugin installieren",
|
|
632
633
|
"installed": "Installiert",
|
|
634
|
+
"legacyTag": "Veraltetes Plugin",
|
|
633
635
|
"list": "Plugin-Liste",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "Beschreibung",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "Providers Supporting This Model"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "Built-in",
|
|
619
620
|
"community": "Community Plugins",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "Install Plugin",
|
|
632
633
|
"installed": "Installed",
|
|
634
|
+
"legacyTag": "Legacy",
|
|
633
635
|
"list": "Plugin List",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "Description",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "Proveedores que admiten este modelo"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "Complemento incorporado",
|
|
619
620
|
"community": "Complementos de la comunidad",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "Instalar complemento",
|
|
632
633
|
"installed": "Instalado",
|
|
634
|
+
"legacyTag": "Complemento heredado",
|
|
633
635
|
"list": "Lista de complementos",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "Descripción",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "ارائهدهندگان پشتیبانی شده برای این مدل"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "افزونه داخلی",
|
|
619
620
|
"community": "پلاگینهای انجمن",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "نصب پلاگین",
|
|
632
633
|
"installed": "نصب شده",
|
|
634
|
+
"legacyTag": "افزونه قدیمی",
|
|
633
635
|
"list": "فهرست پلاگینها",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "توضیحات",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "Fournisseurs prenant en charge ce modèle"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "Plugin intégré",
|
|
619
620
|
"community": "Plugins communautaires",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "Installer le plugin",
|
|
632
633
|
"installed": "Installé",
|
|
634
|
+
"legacyTag": "Ancien plugin",
|
|
633
635
|
"list": "Liste des plugins",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "Description",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "Fornitori supportati da questo modello"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "Plugin integrato",
|
|
619
620
|
"community": "Plugin della comunità",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "Installa plugin",
|
|
632
633
|
"installed": "Installato",
|
|
634
|
+
"legacyTag": "Plugin legacy",
|
|
633
635
|
"list": "Elenco plugin",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "Descrizione",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "このモデルをサポートするプロバイダー"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "内蔵プラグイン",
|
|
619
620
|
"community": "コミュニティプラグイン",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "プラグインをインストール",
|
|
632
633
|
"installed": "インストール済み",
|
|
634
|
+
"legacyTag": "旧バージョンプラグイン",
|
|
633
635
|
"list": "プラグインリスト",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "説明",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "이 모델을 지원하는 서비스 제공자"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "내장 플러그인",
|
|
619
620
|
"community": "커뮤니티 플러그인",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "플러그인 설치",
|
|
632
633
|
"installed": "설치됨",
|
|
634
|
+
"legacyTag": "구버전 플러그인",
|
|
633
635
|
"list": "플러그인 목록",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "설명",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "Providers die dit model ondersteunen"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "Ingebouwde plug-in",
|
|
619
620
|
"community": "Gemeenschapsplugins",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "Plugin installeren",
|
|
632
633
|
"installed": "Geïnstalleerd",
|
|
634
|
+
"legacyTag": "Verouderde plug-in",
|
|
633
635
|
"list": "Pluginlijst",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "Beschrijving",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "Dostawcy obsługujący ten model"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "Wbudowana wtyczka",
|
|
619
620
|
"community": "Wtyczki społecznościowe",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "Zainstaluj wtyczkę",
|
|
632
633
|
"installed": "Zainstalowane",
|
|
634
|
+
"legacyTag": "Starsza wersja wtyczki",
|
|
633
635
|
"list": "Lista wtyczek",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "Opis",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "Provedores que suportam este modelo"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "Plugin Integrado",
|
|
619
620
|
"community": "Plugins da Comunidade",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "Instalar Plugin",
|
|
632
633
|
"installed": "Instalado",
|
|
634
|
+
"legacyTag": "Plugin Legado",
|
|
633
635
|
"list": "Lista de Plugins",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "Descrição",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "Поставщики, поддерживающие эту модель"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "Встроенный плагин",
|
|
619
620
|
"community": "Сообщество плагинов",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "Установить плагин",
|
|
632
633
|
"installed": "Установлено",
|
|
634
|
+
"legacyTag": "Устаревший плагин",
|
|
633
635
|
"list": "Список плагинов",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "Описание",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "Bu modeli destekleyen sağlayıcılar"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "Yerleşik Eklenti",
|
|
619
620
|
"community": "Topluluk Eklentisi",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "Eklenti Yükle",
|
|
632
633
|
"installed": "Yüklü",
|
|
634
|
+
"legacyTag": "Eski Sürüm Eklenti",
|
|
633
635
|
"list": "Eklenti Listesi",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "Açıklama",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "Nhà cung cấp hỗ trợ mô hình này"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "Plugin tích hợp sẵn",
|
|
619
620
|
"community": "Plugin cộng đồng",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "Cài đặt plugin",
|
|
632
633
|
"installed": "Đã cài đặt",
|
|
634
|
+
"legacyTag": "Plugin phiên bản cũ",
|
|
633
635
|
"list": "Danh sách plugin",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "Mô tả",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "支持该模型的服务商"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "内置插件",
|
|
619
620
|
"community": "社区插件",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "安装插件",
|
|
632
633
|
"installed": "已安装",
|
|
634
|
+
"legacyTag": "旧版插件",
|
|
633
635
|
"list": "插件列表",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "描述",
|
|
@@ -616,6 +616,7 @@
|
|
|
616
616
|
"supportedProviders": "支持該模型的服務商"
|
|
617
617
|
},
|
|
618
618
|
"plugins": {
|
|
619
|
+
"builtinTag": "內建外掛",
|
|
619
620
|
"community": "社區插件",
|
|
620
621
|
"details": {
|
|
621
622
|
"settings": {
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
},
|
|
631
632
|
"install": "安裝插件",
|
|
632
633
|
"installed": "已安裝",
|
|
634
|
+
"legacyTag": "舊版外掛",
|
|
633
635
|
"list": "插件列表",
|
|
634
636
|
"meta": {
|
|
635
637
|
"description": "描述",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/lobehub",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.155",
|
|
4
4
|
"description": "LobeHub - an open-source,comprehensive AI Agent framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -4,9 +4,9 @@ export interface PythonOptions {
|
|
|
4
4
|
*/
|
|
5
5
|
pyodideIndexUrl?: string;
|
|
6
6
|
/**
|
|
7
|
-
* PyPI
|
|
7
|
+
* PyPI index URL, must support [JSON API](https://warehouse.pypa.io/api-reference/json.html)
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* Default value: `https://pypi.org/pypi/{package_name}/json`
|
|
10
10
|
*/
|
|
11
11
|
pypiIndexUrl?: string;
|
|
12
12
|
}
|
|
@@ -46,7 +46,19 @@ export interface PluginListResponse {
|
|
|
46
46
|
totalPages: number;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Plugin source types
|
|
51
|
+
* - legacy: From old plugin list (_getPluginList)
|
|
52
|
+
* - market: From Market SDK (getMcpDetail)
|
|
53
|
+
* - builtin: From LobeHub builtin tools
|
|
54
|
+
*/
|
|
55
|
+
export type PluginSource = 'legacy' | 'market' | 'builtin';
|
|
56
|
+
|
|
49
57
|
export interface DiscoverPluginDetail extends Omit<DiscoverPluginItem, 'manifest'> {
|
|
50
58
|
manifest?: LobeChatPluginManifest | string;
|
|
51
59
|
related: DiscoverPluginItem[];
|
|
60
|
+
/**
|
|
61
|
+
* Plugin source type
|
|
62
|
+
*/
|
|
63
|
+
source?: PluginSource;
|
|
52
64
|
}
|
|
@@ -1,35 +1,96 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PluginSource } from '@lobechat/types';
|
|
2
|
+
import { Avatar, Block, Tag, Text } from '@lobehub/ui';
|
|
2
3
|
import { Skeleton } from 'antd';
|
|
3
4
|
import { createStyles } from 'antd-style';
|
|
4
|
-
import { memo } from 'react';
|
|
5
|
+
import { memo, useMemo } from 'react';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
5
7
|
import { Flexbox } from 'react-layout-kit';
|
|
8
|
+
import { Link } from 'react-router-dom';
|
|
9
|
+
import urlJoin from 'url-join';
|
|
6
10
|
|
|
7
11
|
import { useDiscoverStore } from '@/store/discover';
|
|
8
12
|
|
|
9
13
|
const useStyles = createStyles(({ css, token }) => {
|
|
10
14
|
return {
|
|
15
|
+
clickable: css`
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
|
|
18
|
+
&:hover {
|
|
19
|
+
.plugin-title {
|
|
20
|
+
color: ${token.colorLink};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
`,
|
|
11
24
|
desc: css`
|
|
12
25
|
flex: 1;
|
|
13
26
|
margin: 0 !important;
|
|
14
27
|
font-size: 14px !important;
|
|
15
28
|
color: ${token.colorTextSecondary};
|
|
16
29
|
`,
|
|
30
|
+
noLink: css`
|
|
31
|
+
cursor: default;
|
|
32
|
+
`,
|
|
33
|
+
tag: css`
|
|
34
|
+
flex-shrink: 0;
|
|
35
|
+
`,
|
|
17
36
|
title: css`
|
|
18
37
|
margin: 0 !important;
|
|
19
38
|
font-size: 14px !important;
|
|
20
39
|
font-weight: 500 !important;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
40
|
+
`,
|
|
41
|
+
titleRow: css`
|
|
42
|
+
display: flex;
|
|
43
|
+
gap: 8px;
|
|
44
|
+
align-items: center;
|
|
25
45
|
`,
|
|
26
46
|
};
|
|
27
47
|
});
|
|
28
48
|
|
|
29
|
-
|
|
49
|
+
interface PluginItemProps {
|
|
50
|
+
identifier: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const PluginItem = memo<PluginItemProps>(({ identifier }) => {
|
|
54
|
+
const { t } = useTranslation('discover');
|
|
30
55
|
const usePluginDetail = useDiscoverStore((s) => s.usePluginDetail);
|
|
31
56
|
const { data, isLoading } = usePluginDetail({ identifier, withManifest: false });
|
|
32
|
-
const { styles } = useStyles();
|
|
57
|
+
const { styles, cx } = useStyles();
|
|
58
|
+
|
|
59
|
+
const sourceConfig = useMemo(() => {
|
|
60
|
+
const source: PluginSource = data?.source || 'market';
|
|
61
|
+
|
|
62
|
+
switch (source) {
|
|
63
|
+
case 'builtin': {
|
|
64
|
+
return {
|
|
65
|
+
clickable: false,
|
|
66
|
+
href: undefined,
|
|
67
|
+
isExternal: false,
|
|
68
|
+
tagColor: 'geekblue' as const,
|
|
69
|
+
tagText: t('plugins.builtinTag'),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
case 'legacy': {
|
|
73
|
+
return {
|
|
74
|
+
clickable: true,
|
|
75
|
+
href: data?.homepage,
|
|
76
|
+
isExternal: true,
|
|
77
|
+
tagColor: 'orange' as const,
|
|
78
|
+
tagText: t('plugins.legacyTag'),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// eslint-disable-next-line unicorn/no-useless-switch-case
|
|
82
|
+
case 'market':
|
|
83
|
+
default: {
|
|
84
|
+
return {
|
|
85
|
+
clickable: true,
|
|
86
|
+
href: urlJoin('/discover/plugin', identifier),
|
|
87
|
+
isExternal: false,
|
|
88
|
+
tagColor: undefined,
|
|
89
|
+
tagText: undefined,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}, [data?.source, data?.homepage, identifier, t]);
|
|
33
94
|
|
|
34
95
|
if (isLoading || !data)
|
|
35
96
|
return (
|
|
@@ -38,8 +99,15 @@ const PluginItem = memo<{ identifier: string }>(({ identifier }) => {
|
|
|
38
99
|
</Block>
|
|
39
100
|
);
|
|
40
101
|
|
|
41
|
-
|
|
42
|
-
<Block
|
|
102
|
+
const content = (
|
|
103
|
+
<Block
|
|
104
|
+
className={cx(sourceConfig.clickable ? styles.clickable : styles.noLink)}
|
|
105
|
+
gap={12}
|
|
106
|
+
horizontal
|
|
107
|
+
key={identifier}
|
|
108
|
+
padding={12}
|
|
109
|
+
variant={'outlined'}
|
|
110
|
+
>
|
|
43
111
|
<Avatar avatar={data.avatar} size={40} style={{ flex: 'none' }} />
|
|
44
112
|
<Flexbox
|
|
45
113
|
flex={1}
|
|
@@ -48,9 +116,16 @@ const PluginItem = memo<{ identifier: string }>(({ identifier }) => {
|
|
|
48
116
|
overflow: 'hidden',
|
|
49
117
|
}}
|
|
50
118
|
>
|
|
51
|
-
<
|
|
52
|
-
{
|
|
53
|
-
|
|
119
|
+
<div className={styles.titleRow}>
|
|
120
|
+
<Text as={'h2'} className={cx(styles.title, 'plugin-title')} ellipsis>
|
|
121
|
+
{data.title}
|
|
122
|
+
</Text>
|
|
123
|
+
{sourceConfig.tagText && (
|
|
124
|
+
<Tag className={styles.tag} color={sourceConfig.tagColor} size={'small'}>
|
|
125
|
+
{sourceConfig.tagText}
|
|
126
|
+
</Tag>
|
|
127
|
+
)}
|
|
128
|
+
</div>
|
|
54
129
|
<Text
|
|
55
130
|
as={'p'}
|
|
56
131
|
className={styles.desc}
|
|
@@ -63,6 +138,27 @@ const PluginItem = memo<{ identifier: string }>(({ identifier }) => {
|
|
|
63
138
|
</Flexbox>
|
|
64
139
|
</Block>
|
|
65
140
|
);
|
|
141
|
+
|
|
142
|
+
// For builtin plugins, no link wrapper
|
|
143
|
+
if (!sourceConfig.clickable) {
|
|
144
|
+
return content;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// For external links (legacy plugins), use <a> tag
|
|
148
|
+
if (sourceConfig.isExternal && sourceConfig.href) {
|
|
149
|
+
return (
|
|
150
|
+
<a href={sourceConfig.href} rel="noopener noreferrer" target="_blank">
|
|
151
|
+
{content}
|
|
152
|
+
</a>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// For internal links (market plugins), use Link component
|
|
157
|
+
if (sourceConfig.href) {
|
|
158
|
+
return <Link to={sourceConfig.href}>{content}</Link>;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return content;
|
|
66
162
|
});
|
|
67
163
|
|
|
68
164
|
export default PluginItem;
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { Block } from '@lobehub/ui';
|
|
2
2
|
import { Empty } from 'antd';
|
|
3
|
-
import { Link } from 'react-router-dom';
|
|
4
3
|
import { memo } from 'react';
|
|
5
4
|
import { Flexbox } from 'react-layout-kit';
|
|
6
|
-
import urlJoin from 'url-join';
|
|
7
5
|
|
|
8
6
|
import { useDetailContext } from '../../DetailProvider';
|
|
9
7
|
import PluginItem from './PluginItem';
|
|
@@ -24,11 +22,7 @@ const Plugin = memo(() => {
|
|
|
24
22
|
const identifier =
|
|
25
23
|
typeof item === 'string' ? item : (item as { identifier: string }).identifier;
|
|
26
24
|
|
|
27
|
-
return
|
|
28
|
-
<Link key={identifier} to={urlJoin('/discover/plugin', identifier)}>
|
|
29
|
-
<PluginItem identifier={identifier} />
|
|
30
|
-
</Link>
|
|
31
|
-
);
|
|
25
|
+
return <PluginItem identifier={identifier} key={identifier} />;
|
|
32
26
|
})}
|
|
33
27
|
</Flexbox>
|
|
34
28
|
);
|
|
@@ -29,12 +29,12 @@ const Client = memo<{ mobile?: boolean }>(() => {
|
|
|
29
29
|
|
|
30
30
|
return (
|
|
31
31
|
<>
|
|
32
|
-
<Title more={t('home.more')} moreLink={'/assistant'}>
|
|
32
|
+
<Title more={t('home.more')} moreLink={'/discover/assistant'}>
|
|
33
33
|
{t('home.featuredAssistants')}
|
|
34
34
|
</Title>
|
|
35
35
|
<AssistantList data={assistantList.items} rows={4} />
|
|
36
36
|
<div />
|
|
37
|
-
<Title more={t('home.more')} moreLink={'/mcp'}>
|
|
37
|
+
<Title more={t('home.more')} moreLink={'/discover/mcp'}>
|
|
38
38
|
{t('home.featuredTools')}
|
|
39
39
|
</Title>
|
|
40
40
|
<McpList data={mcpList.items} rows={4} />
|
|
@@ -29,12 +29,12 @@ const HomePage = memo<{ mobile?: boolean }>(() => {
|
|
|
29
29
|
|
|
30
30
|
return (
|
|
31
31
|
<>
|
|
32
|
-
<Title more={t('home.more')} moreLink={'/assistant'}>
|
|
32
|
+
<Title more={t('home.more')} moreLink={'/discover/assistant'}>
|
|
33
33
|
{t('home.featuredAssistants')}
|
|
34
34
|
</Title>
|
|
35
35
|
<AssistantList data={assistantList.items} rows={4} />
|
|
36
36
|
<div />
|
|
37
|
-
<Title more={t('home.more')} moreLink={'/mcp'}>
|
|
37
|
+
<Title more={t('home.more')} moreLink={'/discover/mcp'}>
|
|
38
38
|
{t('home.featuredTools')}
|
|
39
39
|
</Title>
|
|
40
40
|
<McpList data={mcpList.items} rows={4} />
|
|
@@ -56,4 +56,3 @@ DesktopHomePage.displayName = 'DesktopHomePage';
|
|
|
56
56
|
|
|
57
57
|
export { DesktopHomePage, MobileHomePage };
|
|
58
58
|
export default HomePage;
|
|
59
|
-
|
|
@@ -48,6 +48,7 @@ const Title = memo<TitleProps>(
|
|
|
48
48
|
// Check if it's an external link or internal discover route
|
|
49
49
|
const isExternalLink = moreLink?.startsWith('http') ?? false;
|
|
50
50
|
const isDiscoverRoute = moreLink?.startsWith('/discover') ?? false;
|
|
51
|
+
console.log('moreLink', moreLink);
|
|
51
52
|
|
|
52
53
|
let moreLinkElement = null;
|
|
53
54
|
if (moreLink) {
|
|
@@ -60,7 +61,7 @@ const Title = memo<TitleProps>(
|
|
|
60
61
|
);
|
|
61
62
|
} else if (isDiscoverRoute) {
|
|
62
63
|
moreLinkElement = (
|
|
63
|
-
<RouterLink className={styles.more} to={moreLink
|
|
64
|
+
<RouterLink className={styles.more} to={moreLink}>
|
|
64
65
|
<span style={{ marginRight: 4 }}>{more}</span>
|
|
65
66
|
<Icon icon={ChevronRight} />
|
|
66
67
|
</RouterLink>
|
package/src/auth.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import { initBetterAuthSSOProviders } from '@/libs/better-auth/sso';
|
|
14
14
|
import { parseSSOProviders } from '@/libs/better-auth/utils/server';
|
|
15
15
|
import { EmailService } from '@/server/services/email';
|
|
16
|
+
import { UserService } from '@/server/services/user';
|
|
16
17
|
|
|
17
18
|
// Email verification link expiration time (in seconds)
|
|
18
19
|
// Default is 1 hour (3600 seconds) as per Better Auth documentation
|
|
@@ -120,6 +121,26 @@ export const auth = betterAuth({
|
|
|
120
121
|
database: drizzleAdapter(serverDB, {
|
|
121
122
|
provider: 'pg',
|
|
122
123
|
}),
|
|
124
|
+
/**
|
|
125
|
+
* Run user bootstrap for every newly created account (email, magic link, OAuth/social, etc.).
|
|
126
|
+
* Using Better Auth database hooks ensures we catch social flows that bypass /sign-up/* routes.
|
|
127
|
+
* Ref: https://www.better-auth.com/docs/reference/options#databasehooks
|
|
128
|
+
*/
|
|
129
|
+
databaseHooks: {
|
|
130
|
+
user: {
|
|
131
|
+
create: {
|
|
132
|
+
after: async (user) => {
|
|
133
|
+
const userService = new UserService(serverDB);
|
|
134
|
+
await userService.initUser({
|
|
135
|
+
email: user.email,
|
|
136
|
+
id: user.id,
|
|
137
|
+
username: user.username as string | null,
|
|
138
|
+
// TODO: if add phone plugin, we should fill phone here
|
|
139
|
+
});
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
},
|
|
123
144
|
user: {
|
|
124
145
|
additionalFields: {
|
|
125
146
|
username: {
|
|
@@ -623,6 +623,7 @@ export default {
|
|
|
623
623
|
supportedProviders: '支持该模型的服务商',
|
|
624
624
|
},
|
|
625
625
|
plugins: {
|
|
626
|
+
builtinTag: '内置插件',
|
|
626
627
|
community: '社区插件',
|
|
627
628
|
details: {
|
|
628
629
|
settings: {
|
|
@@ -637,6 +638,7 @@ export default {
|
|
|
637
638
|
},
|
|
638
639
|
install: '安装插件',
|
|
639
640
|
installed: '已安装',
|
|
641
|
+
legacyTag: '旧版插件',
|
|
640
642
|
list: '插件列表',
|
|
641
643
|
meta: {
|
|
642
644
|
description: '描述',
|
|
@@ -921,88 +921,110 @@ export class DiscoverService {
|
|
|
921
921
|
}): Promise<DiscoverPluginDetail | undefined> => {
|
|
922
922
|
log('getPluginDetail: params=%O', params);
|
|
923
923
|
const { locale, identifier, withManifest } = params;
|
|
924
|
+
|
|
925
|
+
// Step 1: Try to find in legacy plugin list
|
|
924
926
|
const all = await this._getPluginList(locale);
|
|
925
|
-
|
|
926
|
-
if (
|
|
927
|
-
log(
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
927
|
+
const raw = all.find((item) => item.identifier === identifier);
|
|
928
|
+
if (raw) {
|
|
929
|
+
log('getPluginDetail: found plugin in legacy list for identifier=%s', identifier);
|
|
930
|
+
const mergedRaw = merge(cloneDeep(DEFAULT_DISCOVER_PLUGIN_ITEM), raw);
|
|
931
|
+
const list = await this.getPluginList({
|
|
932
|
+
category: mergedRaw.category,
|
|
933
|
+
locale,
|
|
934
|
+
page: 1,
|
|
935
|
+
pageSize: 7,
|
|
936
|
+
});
|
|
937
|
+
|
|
938
|
+
const plugin: DiscoverPluginDetail = {
|
|
939
|
+
...mergedRaw,
|
|
940
|
+
related: list.items.filter((item) => item.identifier !== mergedRaw.identifier).slice(0, 6),
|
|
941
|
+
source: 'legacy',
|
|
942
|
+
};
|
|
943
|
+
|
|
944
|
+
if (!withManifest || !plugin?.manifest || !isString(plugin?.manifest)) {
|
|
945
|
+
log('getPluginDetail: returning legacy plugin without manifest processing');
|
|
946
|
+
return plugin;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
return plugin;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
// Step 2: Try to find in Market MCP plugins
|
|
953
|
+
log(
|
|
954
|
+
'getPluginDetail: plugin not found in legacy store for identifier=%s, trying MCP plugin',
|
|
955
|
+
identifier,
|
|
956
|
+
);
|
|
957
|
+
try {
|
|
958
|
+
const mcpDetail = await this.getMcpDetail({ identifier, locale });
|
|
959
|
+
const convertedMcp: Partial<DiscoverPluginDetail> = {
|
|
960
|
+
author:
|
|
961
|
+
typeof (mcpDetail as any).author === 'object'
|
|
962
|
+
? (mcpDetail as any).author?.name || ''
|
|
963
|
+
: (mcpDetail as any).author || '',
|
|
964
|
+
avatar: (mcpDetail as any).icon || (mcpDetail as any).avatar || '',
|
|
965
|
+
category: (mcpDetail as any).category as any,
|
|
966
|
+
createdAt: (mcpDetail as any).createdAt || '',
|
|
967
|
+
description: mcpDetail.description || '',
|
|
968
|
+
homepage: mcpDetail.homepage || '',
|
|
969
|
+
identifier: mcpDetail.identifier,
|
|
970
|
+
manifest: undefined,
|
|
971
|
+
related: mcpDetail.related.map((item) => ({
|
|
934
972
|
author:
|
|
935
|
-
typeof (
|
|
936
|
-
? (
|
|
937
|
-
: (
|
|
938
|
-
avatar: (
|
|
939
|
-
category: (
|
|
940
|
-
createdAt: (
|
|
941
|
-
description:
|
|
942
|
-
homepage:
|
|
943
|
-
identifier:
|
|
973
|
+
typeof (item as any).author === 'object'
|
|
974
|
+
? (item as any).author?.name || ''
|
|
975
|
+
: (item as any).author || '',
|
|
976
|
+
avatar: (item as any).icon || (item as any).avatar || '',
|
|
977
|
+
category: (item as any).category as any,
|
|
978
|
+
createdAt: (item as any).createdAt || '',
|
|
979
|
+
description: (item as any).description || '',
|
|
980
|
+
homepage: (item as any).homepage || '',
|
|
981
|
+
identifier: item.identifier,
|
|
944
982
|
manifest: undefined,
|
|
945
|
-
related: mcpDetail.related.map((item) => ({
|
|
946
|
-
author:
|
|
947
|
-
typeof (item as any).author === 'object'
|
|
948
|
-
? (item as any).author?.name || ''
|
|
949
|
-
: (item as any).author || '',
|
|
950
|
-
avatar: (item as any).icon || (item as any).avatar || '',
|
|
951
|
-
category: (item as any).category as any,
|
|
952
|
-
createdAt: (item as any).createdAt || '',
|
|
953
|
-
description: (item as any).description || '',
|
|
954
|
-
homepage: (item as any).homepage || '',
|
|
955
|
-
identifier: item.identifier,
|
|
956
|
-
manifest: undefined,
|
|
957
|
-
schemaVersion: 1,
|
|
958
|
-
tags: (item as any).tags || [],
|
|
959
|
-
title: (item as any).name || item.identifier,
|
|
960
|
-
})) as unknown as DiscoverPluginItem[],
|
|
961
983
|
schemaVersion: 1,
|
|
962
|
-
tags: (
|
|
963
|
-
title: (
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
984
|
+
tags: (item as any).tags || [],
|
|
985
|
+
title: (item as any).name || item.identifier,
|
|
986
|
+
})) as unknown as DiscoverPluginItem[],
|
|
987
|
+
schemaVersion: 1,
|
|
988
|
+
source: 'market',
|
|
989
|
+
tags: (mcpDetail as any).tags || [],
|
|
990
|
+
title: (mcpDetail as any).name || mcpDetail.identifier,
|
|
991
|
+
};
|
|
992
|
+
const plugin = merge(cloneDeep(DEFAULT_DISCOVER_PLUGIN_ITEM), convertedMcp);
|
|
993
|
+
log('getPluginDetail: returning converted MCP plugin');
|
|
994
|
+
return plugin as DiscoverPluginDetail;
|
|
995
|
+
} catch {
|
|
996
|
+
log(
|
|
997
|
+
'getPluginDetail: MCP plugin not found for identifier=%s, trying builtin tools',
|
|
998
|
+
identifier,
|
|
999
|
+
);
|
|
972
1000
|
}
|
|
973
1001
|
|
|
974
|
-
|
|
975
|
-
const
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1002
|
+
// Step 3: Try to find in builtin tools
|
|
1003
|
+
const { builtinTools } = await import('@/tools/index');
|
|
1004
|
+
const builtinTool = builtinTools.find((tool) => tool.identifier === identifier);
|
|
1005
|
+
if (builtinTool) {
|
|
1006
|
+
log('getPluginDetail: found builtin tool for identifier=%s', identifier);
|
|
1007
|
+
const plugin: DiscoverPluginDetail = {
|
|
1008
|
+
author: 'LobeHub',
|
|
1009
|
+
avatar: builtinTool.manifest.meta.avatar || '',
|
|
1010
|
+
category: undefined,
|
|
1011
|
+
createdAt: '',
|
|
1012
|
+
description: builtinTool.manifest.meta.description || '',
|
|
1013
|
+
homepage: 'https://lobehub.com',
|
|
1014
|
+
identifier: builtinTool.identifier,
|
|
1015
|
+
manifest: undefined,
|
|
1016
|
+
related: [],
|
|
1017
|
+
schemaVersion: 1,
|
|
1018
|
+
source: 'builtin',
|
|
1019
|
+
tags: builtinTool.manifest.meta.tags || [],
|
|
1020
|
+
title: builtinTool.manifest.meta.title,
|
|
1021
|
+
};
|
|
1022
|
+
log('getPluginDetail: returning builtin tool plugin');
|
|
989
1023
|
return plugin;
|
|
990
1024
|
}
|
|
991
1025
|
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
// try {
|
|
995
|
-
// const manifest = await getToolManifest(plugin.manifest);
|
|
996
|
-
//
|
|
997
|
-
// return {
|
|
998
|
-
// ...plugin,
|
|
999
|
-
// manifest,
|
|
1000
|
-
// };
|
|
1001
|
-
// } catch {
|
|
1002
|
-
// return plugin;
|
|
1003
|
-
// }
|
|
1004
|
-
|
|
1005
|
-
return plugin;
|
|
1026
|
+
log('getPluginDetail: plugin not found anywhere for identifier=%s', identifier);
|
|
1027
|
+
return;
|
|
1006
1028
|
};
|
|
1007
1029
|
|
|
1008
1030
|
getPluginIdentifiers = async (): Promise<IdentifiersResponse> => {
|
|
@@ -8,6 +8,15 @@ import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
|
|
|
8
8
|
import { S3 } from '@/server/modules/S3';
|
|
9
9
|
import { AgentService } from '@/server/services/agent';
|
|
10
10
|
|
|
11
|
+
type CreatedUser = {
|
|
12
|
+
email?: string | null;
|
|
13
|
+
firstName?: string | null;
|
|
14
|
+
id: string;
|
|
15
|
+
lastName?: string | null;
|
|
16
|
+
phone?: string | null;
|
|
17
|
+
username?: string | null;
|
|
18
|
+
};
|
|
19
|
+
|
|
11
20
|
export class UserService {
|
|
12
21
|
private db: LobeChatDatabase;
|
|
13
22
|
|
|
@@ -15,6 +24,30 @@ export class UserService {
|
|
|
15
24
|
this.db = db;
|
|
16
25
|
}
|
|
17
26
|
|
|
27
|
+
async initUser(user: CreatedUser) {
|
|
28
|
+
const agentService = new AgentService(this.db, user.id);
|
|
29
|
+
await agentService.createInbox();
|
|
30
|
+
|
|
31
|
+
/* ↓ cloud slot ↓ */
|
|
32
|
+
/* ↑ cloud slot ↑ */
|
|
33
|
+
|
|
34
|
+
const analytics = await initializeServerAnalytics();
|
|
35
|
+
analytics?.identify(user.id, {
|
|
36
|
+
email: user.email ?? undefined,
|
|
37
|
+
firstName: user.firstName ?? undefined,
|
|
38
|
+
lastName: user.lastName ?? undefined,
|
|
39
|
+
phone: user.phone ?? undefined,
|
|
40
|
+
username: user.username ?? undefined,
|
|
41
|
+
});
|
|
42
|
+
analytics?.track({
|
|
43
|
+
name: 'user_register_completed',
|
|
44
|
+
properties: {
|
|
45
|
+
spm: 'user_service.init_user.user_created',
|
|
46
|
+
},
|
|
47
|
+
userId: user.id,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
18
51
|
createUser = async (id: string, params: UserJSON) => {
|
|
19
52
|
// Check if user already exists
|
|
20
53
|
const res = await UserModel.findById(this.db, id);
|
|
@@ -34,10 +67,6 @@ export class UserService {
|
|
|
34
67
|
return index === 0;
|
|
35
68
|
});
|
|
36
69
|
|
|
37
|
-
/* ↓ cloud slot ↓ */
|
|
38
|
-
|
|
39
|
-
/* ↑ cloud slot ↑ */
|
|
40
|
-
|
|
41
70
|
// 2. create user in database
|
|
42
71
|
await UserModel.createUser(this.db, {
|
|
43
72
|
avatar: params.image_url,
|
|
@@ -50,30 +79,14 @@ export class UserService {
|
|
|
50
79
|
username: params.username,
|
|
51
80
|
});
|
|
52
81
|
|
|
53
|
-
|
|
54
|
-
const agentService = new AgentService(this.db, id);
|
|
55
|
-
await agentService.createInbox();
|
|
56
|
-
|
|
57
|
-
/* ↓ cloud slot ↓ */
|
|
58
|
-
|
|
59
|
-
/* ↑ cloud slot ↑ */
|
|
60
|
-
|
|
61
|
-
//analytics
|
|
62
|
-
const analytics = await initializeServerAnalytics();
|
|
63
|
-
analytics?.identify(id, {
|
|
82
|
+
await this.initUser({
|
|
64
83
|
email: email?.email_address,
|
|
65
84
|
firstName: params.first_name,
|
|
85
|
+
id,
|
|
66
86
|
lastName: params.last_name,
|
|
67
87
|
phone: phone?.phone_number,
|
|
68
88
|
username: params.username,
|
|
69
89
|
});
|
|
70
|
-
analytics?.track({
|
|
71
|
-
name: 'user_register_completed',
|
|
72
|
-
properties: {
|
|
73
|
-
spm: 'user_service.create_user.user_created',
|
|
74
|
-
},
|
|
75
|
-
userId: id,
|
|
76
|
-
});
|
|
77
90
|
|
|
78
91
|
return { message: 'user created', success: true };
|
|
79
92
|
};
|