@lobehub/lobehub 2.0.0-next.142 → 2.0.0-next.143
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 +25 -0
- package/apps/desktop/package.json +1 -0
- package/apps/desktop/src/main/core/ui/__tests__/MenuManager.test.ts +320 -0
- package/apps/desktop/src/main/core/ui/__tests__/Tray.test.ts +518 -0
- package/apps/desktop/src/main/core/ui/__tests__/TrayManager.test.ts +360 -0
- package/apps/desktop/src/main/menus/impls/BaseMenuPlatform.test.ts +49 -0
- package/apps/desktop/src/main/menus/impls/linux.test.ts +552 -0
- package/apps/desktop/src/main/menus/impls/macOS.test.ts +464 -0
- package/apps/desktop/src/main/menus/impls/windows.test.ts +429 -0
- package/apps/desktop/src/main/modules/fileSearch/__tests__/macOS.integration.test.ts +2 -2
- package/apps/desktop/src/main/services/__tests__/fileSearchSrv.test.ts +402 -0
- package/apps/desktop/src/main/utils/__tests__/file-system.test.ts +91 -0
- package/apps/desktop/src/main/utils/__tests__/logger.test.ts +229 -0
- package/apps/desktop/src/preload/electronApi.test.ts +142 -0
- package/apps/desktop/src/preload/invoke.test.ts +145 -0
- package/apps/desktop/src/preload/routeInterceptor.test.ts +374 -0
- package/apps/desktop/src/preload/streamer.test.ts +365 -0
- package/apps/desktop/vitest.config.mts +1 -0
- package/changelog/v1.json +9 -0
- package/locales/ar/marketAuth.json +13 -0
- package/locales/bg-BG/marketAuth.json +13 -0
- package/locales/de-DE/marketAuth.json +13 -0
- package/locales/en-US/marketAuth.json +13 -0
- package/locales/es-ES/marketAuth.json +13 -0
- package/locales/fa-IR/marketAuth.json +13 -0
- package/locales/fr-FR/marketAuth.json +13 -0
- package/locales/it-IT/marketAuth.json +13 -0
- package/locales/ja-JP/marketAuth.json +13 -0
- package/locales/ko-KR/marketAuth.json +13 -0
- package/locales/nl-NL/marketAuth.json +13 -0
- package/locales/pl-PL/marketAuth.json +13 -0
- package/locales/pt-BR/marketAuth.json +13 -0
- package/locales/ru-RU/marketAuth.json +13 -0
- package/locales/tr-TR/marketAuth.json +13 -0
- package/locales/vi-VN/marketAuth.json +13 -0
- package/locales/zh-CN/marketAuth.json +13 -0
- package/locales/zh-TW/marketAuth.json +13 -0
- package/package.json +1 -1
- package/packages/database/src/models/user.ts +2 -0
- package/packages/types/src/discover/mcp.ts +2 -1
- package/packages/types/src/tool/plugin.ts +2 -1
- package/src/app/[variants]/(main)/chat/settings/features/SmartAgentActionButton/MarketPublishButton.tsx +0 -2
- package/src/app/[variants]/(main)/discover/(detail)/mcp/features/Sidebar/ActionButton/index.tsx +33 -7
- package/src/features/PluginStore/McpList/List/Action.tsx +20 -1
- package/src/layout/AuthProvider/MarketAuth/MarketAuthConfirmModal.tsx +158 -0
- package/src/layout/AuthProvider/MarketAuth/MarketAuthProvider.tsx +130 -14
- package/src/libs/mcp/types.ts +8 -0
- package/src/locales/default/marketAuth.ts +13 -0
- package/src/server/routers/lambda/market/index.ts +85 -2
- package/src/server/services/discover/index.ts +45 -4
- package/src/services/discover.ts +1 -1
- package/src/services/mcp.ts +18 -3
- package/src/store/tool/slices/mcpStore/action.test.ts +141 -0
- package/src/store/tool/slices/mcpStore/action.ts +153 -11
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
+
"authorize": {
|
|
3
|
+
"cancel": "Anuluj",
|
|
4
|
+
"confirm": "Autoryzuj użycie",
|
|
5
|
+
"description": {
|
|
6
|
+
"and": "oraz",
|
|
7
|
+
"prefix": "Klikając „Autoryzuj użycie”, wyrażasz zgodę na",
|
|
8
|
+
"privacy": "Politykę prywatności",
|
|
9
|
+
"terms": "Warunki korzystania z usługi"
|
|
10
|
+
},
|
|
11
|
+
"title": "Potwierdź autoryzację"
|
|
12
|
+
},
|
|
2
13
|
"callback": {
|
|
3
14
|
"buttons": {
|
|
4
15
|
"close": "Zamknij okno"
|
|
@@ -33,8 +44,10 @@
|
|
|
33
44
|
"stateMissing": "Nie znaleziono stanu autoryzacji, spróbuj ponownie."
|
|
34
45
|
},
|
|
35
46
|
"messages": {
|
|
47
|
+
"authorized": "Autoryzacja usługi LobeHub zakończona pomyślnie",
|
|
36
48
|
"loading": "Uruchamianie procesu autoryzacji...",
|
|
37
49
|
"success": {
|
|
50
|
+
"cloudMcpInstall": "Autoryzacja zakończona sukcesem! Możesz teraz zainstalować wtyczkę Cloud MCP.",
|
|
38
51
|
"submit": "Autoryzacja zakończona sukcesem! Możesz teraz opublikować asystenta.",
|
|
39
52
|
"upload": "Autoryzacja zakończona sukcesem! Możesz teraz opublikować nową wersję."
|
|
40
53
|
}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
+
"authorize": {
|
|
3
|
+
"cancel": "Cancelar",
|
|
4
|
+
"confirm": "Autorizar uso",
|
|
5
|
+
"description": {
|
|
6
|
+
"and": "e",
|
|
7
|
+
"prefix": "Ao clicar em autorizar uso, você concorda com",
|
|
8
|
+
"privacy": "Política de Privacidade",
|
|
9
|
+
"terms": "Termos de Serviço"
|
|
10
|
+
},
|
|
11
|
+
"title": "Confirmar Autorização"
|
|
12
|
+
},
|
|
2
13
|
"callback": {
|
|
3
14
|
"buttons": {
|
|
4
15
|
"close": "Fechar janela"
|
|
@@ -33,8 +44,10 @@
|
|
|
33
44
|
"stateMissing": "Estado de autorização não encontrado, tente novamente."
|
|
34
45
|
},
|
|
35
46
|
"messages": {
|
|
47
|
+
"authorized": "Autorização do serviço LobeHub realizada com sucesso",
|
|
36
48
|
"loading": "Iniciando o processo de autorização...",
|
|
37
49
|
"success": {
|
|
50
|
+
"cloudMcpInstall": "Autorização bem-sucedida! Agora você pode instalar o plugin Cloud MCP.",
|
|
38
51
|
"submit": "Autorização bem-sucedida! Agora você pode publicar o assistente.",
|
|
39
52
|
"upload": "Autorização bem-sucedida! Agora você pode publicar uma nova versão."
|
|
40
53
|
}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
+
"authorize": {
|
|
3
|
+
"cancel": "Отмена",
|
|
4
|
+
"confirm": "Подтвердить доступ",
|
|
5
|
+
"description": {
|
|
6
|
+
"and": "и",
|
|
7
|
+
"prefix": "Нажимая «Подтвердить доступ», вы соглашаетесь с",
|
|
8
|
+
"privacy": "Политикой конфиденциальности",
|
|
9
|
+
"terms": "Условиями обслуживания"
|
|
10
|
+
},
|
|
11
|
+
"title": "Подтвердить авторизацию"
|
|
12
|
+
},
|
|
2
13
|
"callback": {
|
|
3
14
|
"buttons": {
|
|
4
15
|
"close": "Закрыть окно"
|
|
@@ -33,8 +44,10 @@
|
|
|
33
44
|
"stateMissing": "Состояние авторизации не найдено, пожалуйста, попробуйте снова."
|
|
34
45
|
},
|
|
35
46
|
"messages": {
|
|
47
|
+
"authorized": "Авторизация сервиса LobeHub прошла успешно",
|
|
36
48
|
"loading": "Запуск процесса авторизации...",
|
|
37
49
|
"success": {
|
|
50
|
+
"cloudMcpInstall": "Доступ успешно предоставлен! Теперь вы можете установить плагин Cloud MCP.",
|
|
38
51
|
"submit": "Авторизация прошла успешно! Теперь вы можете опубликовать помощника.",
|
|
39
52
|
"upload": "Авторизация прошла успешно! Теперь вы можете опубликовать новую версию."
|
|
40
53
|
}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
+
"authorize": {
|
|
3
|
+
"cancel": "İptal",
|
|
4
|
+
"confirm": "Kullanıma Yetki Ver",
|
|
5
|
+
"description": {
|
|
6
|
+
"and": "ve",
|
|
7
|
+
"prefix": "Kullanıma yetki ver'e tıklayarak şu şartları kabul etmiş olursunuz:",
|
|
8
|
+
"privacy": "Gizlilik Politikası",
|
|
9
|
+
"terms": "Hizmet Şartları"
|
|
10
|
+
},
|
|
11
|
+
"title": "Yetkilendirmeyi Onayla"
|
|
12
|
+
},
|
|
2
13
|
"callback": {
|
|
3
14
|
"buttons": {
|
|
4
15
|
"close": "Pencereyi Kapat"
|
|
@@ -33,8 +44,10 @@
|
|
|
33
44
|
"stateMissing": "Yetkilendirme durumu bulunamadı, lütfen tekrar deneyin."
|
|
34
45
|
},
|
|
35
46
|
"messages": {
|
|
47
|
+
"authorized": "LobeHub hizmet yetkilendirmesi başarıyla tamamlandı",
|
|
36
48
|
"loading": "Yetkilendirme süreci başlatılıyor...",
|
|
37
49
|
"success": {
|
|
50
|
+
"cloudMcpInstall": "Yetkilendirme başarılı! Artık Cloud MCP eklentisini yükleyebilirsiniz.",
|
|
38
51
|
"submit": "Yetkilendirme başarılı! Artık asistan yayınlayabilirsiniz.",
|
|
39
52
|
"upload": "Yetkilendirme başarılı! Artık yeni bir sürüm yayınlayabilirsiniz."
|
|
40
53
|
}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
+
"authorize": {
|
|
3
|
+
"cancel": "Hủy",
|
|
4
|
+
"confirm": "Ủy quyền sử dụng",
|
|
5
|
+
"description": {
|
|
6
|
+
"and": "và",
|
|
7
|
+
"prefix": "Bằng cách nhấp vào ủy quyền sử dụng, bạn đồng ý với",
|
|
8
|
+
"privacy": "Chính sách quyền riêng tư",
|
|
9
|
+
"terms": "Điều khoản dịch vụ"
|
|
10
|
+
},
|
|
11
|
+
"title": "Xác nhận ủy quyền"
|
|
12
|
+
},
|
|
2
13
|
"callback": {
|
|
3
14
|
"buttons": {
|
|
4
15
|
"close": "Đóng cửa sổ"
|
|
@@ -33,8 +44,10 @@
|
|
|
33
44
|
"stateMissing": "Không tìm thấy trạng thái xác thực, vui lòng thử lại."
|
|
34
45
|
},
|
|
35
46
|
"messages": {
|
|
47
|
+
"authorized": "Dịch vụ LobeHub đã được cấp quyền thành công",
|
|
36
48
|
"loading": "Đang khởi động quy trình xác thực...",
|
|
37
49
|
"success": {
|
|
50
|
+
"cloudMcpInstall": "Ủy quyền thành công! Bây giờ bạn có thể cài đặt plugin Cloud MCP.",
|
|
38
51
|
"submit": "Xác thực thành công! Bây giờ bạn có thể xuất bản trợ lý.",
|
|
39
52
|
"upload": "Xác thực thành công! Bây giờ bạn có thể xuất bản phiên bản mới."
|
|
40
53
|
}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
+
"authorize": {
|
|
3
|
+
"cancel": "取消",
|
|
4
|
+
"confirm": "授权使用",
|
|
5
|
+
"description": {
|
|
6
|
+
"and": "和",
|
|
7
|
+
"prefix": "点击授权使用即视为同意",
|
|
8
|
+
"privacy": "隐私协议",
|
|
9
|
+
"terms": "服务条款"
|
|
10
|
+
},
|
|
11
|
+
"title": "确认授权"
|
|
12
|
+
},
|
|
2
13
|
"callback": {
|
|
3
14
|
"buttons": {
|
|
4
15
|
"close": "关闭窗口"
|
|
@@ -33,8 +44,10 @@
|
|
|
33
44
|
"stateMissing": "未找到授权状态,请重试。"
|
|
34
45
|
},
|
|
35
46
|
"messages": {
|
|
47
|
+
"authorized": "LobeHub 服务授权成功",
|
|
36
48
|
"loading": "正在启动授权流程...",
|
|
37
49
|
"success": {
|
|
50
|
+
"cloudMcpInstall": "授权成功!现在可以安装 Cloud MCP 插件了。",
|
|
38
51
|
"submit": "授权成功!现在可以发布助手了。",
|
|
39
52
|
"upload": "授权成功!现在可以发布新版本了。"
|
|
40
53
|
}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
+
"authorize": {
|
|
3
|
+
"cancel": "取消",
|
|
4
|
+
"confirm": "授權使用",
|
|
5
|
+
"description": {
|
|
6
|
+
"and": "和",
|
|
7
|
+
"prefix": "點擊授權使用即視為同意",
|
|
8
|
+
"privacy": "隱私協議",
|
|
9
|
+
"terms": "服務條款"
|
|
10
|
+
},
|
|
11
|
+
"title": "確認授權"
|
|
12
|
+
},
|
|
2
13
|
"callback": {
|
|
3
14
|
"buttons": {
|
|
4
15
|
"close": "關閉視窗"
|
|
@@ -33,8 +44,10 @@
|
|
|
33
44
|
"stateMissing": "找不到授權狀態,請重試。"
|
|
34
45
|
},
|
|
35
46
|
"messages": {
|
|
47
|
+
"authorized": "LobeHub 服務授權成功",
|
|
36
48
|
"loading": "正在啟動授權流程⋯⋯",
|
|
37
49
|
"success": {
|
|
50
|
+
"cloudMcpInstall": "授權成功!現在可以安裝 Cloud MCP 外掛了。",
|
|
38
51
|
"submit": "授權成功!現在可以發佈助手了。",
|
|
39
52
|
"upload": "授權成功!現在可以發佈新版本了。"
|
|
40
53
|
}
|
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.143",
|
|
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",
|
|
@@ -80,6 +80,7 @@ export class UserModel {
|
|
|
80
80
|
settingsImage: userSettings.image,
|
|
81
81
|
settingsKeyVaults: userSettings.keyVaults,
|
|
82
82
|
settingsLanguageModel: userSettings.languageModel,
|
|
83
|
+
settingsMarket: userSettings.market,
|
|
83
84
|
settingsSystemAgent: userSettings.systemAgent,
|
|
84
85
|
settingsTTS: userSettings.tts,
|
|
85
86
|
settingsTool: userSettings.tool,
|
|
@@ -112,6 +113,7 @@ export class UserModel {
|
|
|
112
113
|
image: state.settingsImage || {},
|
|
113
114
|
keyVaults: decryptKeyVaults,
|
|
114
115
|
languageModel: state.settingsLanguageModel || {},
|
|
116
|
+
market: state.settingsMarket || undefined,
|
|
115
117
|
systemAgent: state.settingsSystemAgent || {},
|
|
116
118
|
tool: state.settingsTool || {},
|
|
117
119
|
tts: state.settingsTTS || {},
|
|
@@ -41,7 +41,7 @@ export enum McpNavKey {
|
|
|
41
41
|
|
|
42
42
|
export enum McpConnectionType {
|
|
43
43
|
http = 'http',
|
|
44
|
-
stdio = 'stdio'
|
|
44
|
+
stdio = 'stdio',
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
export type DiscoverMcpItem = PluginItem;
|
|
@@ -60,6 +60,7 @@ export interface McpQueryParams {
|
|
|
60
60
|
export type McpListResponse = PluginListResponse;
|
|
61
61
|
|
|
62
62
|
export interface DiscoverMcpDetail extends PluginItemDetail {
|
|
63
|
+
haveCloudEndpoint?: boolean;
|
|
63
64
|
isClaimed?: boolean;
|
|
64
65
|
related: DiscoverMcpItem[];
|
|
65
66
|
}
|
|
@@ -25,8 +25,9 @@ export interface CustomPluginParams {
|
|
|
25
25
|
args?: string[];
|
|
26
26
|
env?: Record<string, string>;
|
|
27
27
|
command?: string;
|
|
28
|
-
type: 'http' | 'stdio';
|
|
28
|
+
type: 'http' | 'stdio' | 'cloud';
|
|
29
29
|
url?: string;
|
|
30
|
+
cloudEndPoint?: string; // Cloud gateway endpoint for cloud type
|
|
30
31
|
// Added authentication configuration support
|
|
31
32
|
auth?: {
|
|
32
33
|
type: 'none' | 'bearer' | 'oauth2';
|
|
@@ -87,9 +87,7 @@ const MarketPublishButton = memo<MarketPublishButtonProps>(
|
|
|
87
87
|
`[MarketPublishButton][${action}] User not authenticated, starting authorization`,
|
|
88
88
|
);
|
|
89
89
|
try {
|
|
90
|
-
message.loading({ content: tMarketAuth('messages.loading'), key: 'market-auth' });
|
|
91
90
|
const accountId = await signIn();
|
|
92
|
-
message.success({ content: buttonCopy.successMessage, key: 'market-auth' });
|
|
93
91
|
|
|
94
92
|
let targetAction: MarketPublishAction = action;
|
|
95
93
|
|
package/src/app/[variants]/(main)/discover/(detail)/mcp/features/Sidebar/ActionButton/index.tsx
CHANGED
|
@@ -10,6 +10,7 @@ import { Flexbox } from 'react-layout-kit';
|
|
|
10
10
|
|
|
11
11
|
import MCPInstallProgress from '@/features/MCP/MCPInstallProgress';
|
|
12
12
|
import { useDetailContext } from '@/features/MCPPluginDetail/DetailProvider';
|
|
13
|
+
import { useMarketAuth } from '@/layout/AuthProvider/MarketAuth';
|
|
13
14
|
import { useToolStore } from '@/store/tool';
|
|
14
15
|
import { pluginSelectors } from '@/store/tool/slices/plugin/selectors';
|
|
15
16
|
|
|
@@ -23,9 +24,11 @@ const useStyles = createStyles(({ css }) => ({
|
|
|
23
24
|
|
|
24
25
|
const ActionButton = memo(() => {
|
|
25
26
|
const { t } = useTranslation(['discover', 'plugin']);
|
|
26
|
-
const
|
|
27
|
+
const detailContext = useDetailContext();
|
|
28
|
+
const { identifier, haveCloudEndpoint } = detailContext;
|
|
27
29
|
const { styles } = useStyles();
|
|
28
30
|
const [isLoading, setIsLoading] = useState(false);
|
|
31
|
+
const { isAuthenticated, isLoading: isAuthLoading, signIn } = useMarketAuth();
|
|
29
32
|
|
|
30
33
|
const [installed, installMCPPlugin, uninstallMCPPlugin] = useToolStore((s) => [
|
|
31
34
|
pluginSelectors.isPluginInstalled(identifier!)(s),
|
|
@@ -33,24 +36,47 @@ const ActionButton = memo(() => {
|
|
|
33
36
|
s.uninstallMCPPlugin,
|
|
34
37
|
]);
|
|
35
38
|
|
|
39
|
+
// Check if this is a cloud MCP plugin
|
|
40
|
+
const isCloudMcp = haveCloudEndpoint;
|
|
41
|
+
|
|
36
42
|
const installPlugin = async () => {
|
|
37
43
|
if (!identifier) return;
|
|
38
|
-
setIsLoading(true);
|
|
39
44
|
|
|
40
|
-
|
|
45
|
+
// If this is a cloud MCP and user is not authenticated, request authorization first
|
|
46
|
+
if (isCloudMcp && !isAuthenticated) {
|
|
47
|
+
try {
|
|
48
|
+
await signIn();
|
|
49
|
+
} catch {
|
|
50
|
+
return; // Don't proceed with installation if auth fails
|
|
51
|
+
}
|
|
52
|
+
}
|
|
41
53
|
|
|
42
|
-
|
|
54
|
+
// Proceed with installation
|
|
55
|
+
setIsLoading(true);
|
|
56
|
+
try {
|
|
57
|
+
await installMCPPlugin(identifier);
|
|
58
|
+
} finally {
|
|
59
|
+
setIsLoading(false);
|
|
60
|
+
}
|
|
43
61
|
};
|
|
44
62
|
|
|
63
|
+
const buttonLoading = isLoading || isAuthLoading;
|
|
64
|
+
|
|
45
65
|
return installed ? (
|
|
46
66
|
<Flexbox gap={8} horizontal>
|
|
47
|
-
<Button
|
|
67
|
+
<Button
|
|
68
|
+
block
|
|
69
|
+
className={styles.button}
|
|
70
|
+
disabled={buttonLoading}
|
|
71
|
+
size={'large'}
|
|
72
|
+
type={'default'}
|
|
73
|
+
>
|
|
48
74
|
{t('plugins.installed')}
|
|
49
75
|
</Button>
|
|
50
76
|
|
|
51
77
|
<Button
|
|
52
78
|
icon={<Icon icon={Trash2Icon} size={20} />}
|
|
53
|
-
loading={
|
|
79
|
+
loading={buttonLoading}
|
|
54
80
|
onClick={async () => {
|
|
55
81
|
setIsLoading(true);
|
|
56
82
|
await uninstallMCPPlugin(identifier!);
|
|
@@ -68,7 +94,7 @@ const ActionButton = memo(() => {
|
|
|
68
94
|
<Button
|
|
69
95
|
block
|
|
70
96
|
className={styles.button}
|
|
71
|
-
loading={
|
|
97
|
+
loading={buttonLoading}
|
|
72
98
|
onClick={installPlugin}
|
|
73
99
|
size={'large'}
|
|
74
100
|
type={'primary'}
|
|
@@ -5,6 +5,7 @@ import { memo } from 'react';
|
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
import { Flexbox } from 'react-layout-kit';
|
|
7
7
|
|
|
8
|
+
import { useMarketAuth } from '@/layout/AuthProvider/MarketAuth';
|
|
8
9
|
import { useAgentStore } from '@/store/agent';
|
|
9
10
|
import { agentSelectors } from '@/store/agent/selectors';
|
|
10
11
|
import { useToolStore } from '@/store/tool';
|
|
@@ -15,13 +16,14 @@ interface ActionsProps {
|
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
const Actions = memo<ActionsProps>(({ identifier }) => {
|
|
18
|
-
const [installed, installing, unInstallPlugin, installMCPPlugin, cancelInstallMCPPlugin] =
|
|
19
|
+
const [installed, installing, unInstallPlugin, installMCPPlugin, cancelInstallMCPPlugin, plugin] =
|
|
19
20
|
useToolStore((s) => [
|
|
20
21
|
pluginSelectors.isPluginInstalled(identifier)(s),
|
|
21
22
|
mcpStoreSelectors.isMCPInstalling(identifier)(s),
|
|
22
23
|
s.uninstallPlugin,
|
|
23
24
|
s.installMCPPlugin,
|
|
24
25
|
s.cancelInstallMCPPlugin,
|
|
26
|
+
mcpStoreSelectors.getPluginById(identifier)(s),
|
|
25
27
|
]);
|
|
26
28
|
|
|
27
29
|
const { t } = useTranslation('plugin');
|
|
@@ -30,6 +32,10 @@ const Actions = memo<ActionsProps>(({ identifier }) => {
|
|
|
30
32
|
agentSelectors.currentAgentPlugins(s).includes(identifier),
|
|
31
33
|
]);
|
|
32
34
|
const { modal } = App.useApp();
|
|
35
|
+
const { isAuthenticated, signIn } = useMarketAuth();
|
|
36
|
+
|
|
37
|
+
// Check if this is a cloud MCP plugin
|
|
38
|
+
const isCloudMcp = !!((plugin as any)?.cloudEndPoint || (plugin as any)?.haveCloudEndpoint);
|
|
33
39
|
|
|
34
40
|
return (
|
|
35
41
|
<Flexbox align={'center'} horizontal>
|
|
@@ -86,6 +92,19 @@ const Actions = memo<ActionsProps>(({ identifier }) => {
|
|
|
86
92
|
onClick={async (e) => {
|
|
87
93
|
e.stopPropagation();
|
|
88
94
|
|
|
95
|
+
// If this is a cloud MCP and user is not authenticated, request authorization first
|
|
96
|
+
if (isCloudMcp && !isAuthenticated) {
|
|
97
|
+
console.log(
|
|
98
|
+
'[MCPListAction] Cloud MCP detected, user not authenticated, starting authorization',
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
await signIn();
|
|
103
|
+
} catch {
|
|
104
|
+
return; // Don't proceed with installation if auth fails
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
89
108
|
const isSuccess = await installMCPPlugin(identifier);
|
|
90
109
|
|
|
91
110
|
if (isSuccess) {
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Modal } from '@lobehub/ui';
|
|
4
|
+
import { createStyles } from 'antd-style';
|
|
5
|
+
import { ArrowRight, ShieldCheck } from 'lucide-react';
|
|
6
|
+
import { memo } from 'react';
|
|
7
|
+
import { useTranslation } from 'react-i18next';
|
|
8
|
+
|
|
9
|
+
const useStyles = createStyles(({ css, token }) => ({
|
|
10
|
+
content: css`
|
|
11
|
+
.ant-modal-content {
|
|
12
|
+
overflow: hidden;
|
|
13
|
+
padding: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.ant-modal-header {
|
|
17
|
+
margin-block-end: 0;
|
|
18
|
+
padding: 0;
|
|
19
|
+
border-block-end: none;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.ant-modal-body {
|
|
23
|
+
padding: 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.ant-modal-footer {
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
justify-content: space-between;
|
|
30
|
+
|
|
31
|
+
margin-block-start: 0;
|
|
32
|
+
padding-block: 16px;
|
|
33
|
+
padding-inline: 24px;
|
|
34
|
+
border-block-start: 1px solid ${token.colorBorder};
|
|
35
|
+
|
|
36
|
+
background: ${token.colorBgContainer};
|
|
37
|
+
|
|
38
|
+
.ant-btn {
|
|
39
|
+
margin: 0;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
`,
|
|
43
|
+
description: css`
|
|
44
|
+
font-size: 14px;
|
|
45
|
+
line-height: 1.5;
|
|
46
|
+
color: ${token.colorTextSecondary};
|
|
47
|
+
text-align: center;
|
|
48
|
+
|
|
49
|
+
a {
|
|
50
|
+
color: ${token.colorPrimary};
|
|
51
|
+
text-decoration: none;
|
|
52
|
+
|
|
53
|
+
&:hover {
|
|
54
|
+
text-decoration: underline;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.highlight {
|
|
59
|
+
font-weight: 500;
|
|
60
|
+
color: ${token.colorText};
|
|
61
|
+
}
|
|
62
|
+
`,
|
|
63
|
+
header: css`
|
|
64
|
+
padding-block: 24px 16px;
|
|
65
|
+
padding-inline: 24px;
|
|
66
|
+
text-align: center;
|
|
67
|
+
`,
|
|
68
|
+
iconWrapper: css`
|
|
69
|
+
display: flex;
|
|
70
|
+
flex-direction: column;
|
|
71
|
+
align-items: center;
|
|
72
|
+
|
|
73
|
+
padding-block: 32px 0;
|
|
74
|
+
padding-inline: 0;
|
|
75
|
+
`,
|
|
76
|
+
okButton: css`
|
|
77
|
+
display: flex;
|
|
78
|
+
gap: 8px;
|
|
79
|
+
align-items: center;
|
|
80
|
+
`,
|
|
81
|
+
shieldIcon: css`
|
|
82
|
+
display: flex;
|
|
83
|
+
align-items: center;
|
|
84
|
+
justify-content: center;
|
|
85
|
+
|
|
86
|
+
width: 64px;
|
|
87
|
+
height: 64px;
|
|
88
|
+
border-radius: 50%;
|
|
89
|
+
|
|
90
|
+
background: ${token.colorPrimaryBg};
|
|
91
|
+
|
|
92
|
+
svg {
|
|
93
|
+
width: 36px;
|
|
94
|
+
height: 36px;
|
|
95
|
+
color: ${token.colorPrimary};
|
|
96
|
+
}
|
|
97
|
+
`,
|
|
98
|
+
title: css`
|
|
99
|
+
margin-block-end: 24px;
|
|
100
|
+
font-size: 18px;
|
|
101
|
+
font-weight: 600;
|
|
102
|
+
color: ${token.colorText};
|
|
103
|
+
`,
|
|
104
|
+
}));
|
|
105
|
+
|
|
106
|
+
interface MarketAuthConfirmModalProps {
|
|
107
|
+
onCancel: () => void;
|
|
108
|
+
onConfirm: () => void;
|
|
109
|
+
open: boolean;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const MarketAuthConfirmModal = memo<MarketAuthConfirmModalProps>(
|
|
113
|
+
({ open, onConfirm, onCancel }) => {
|
|
114
|
+
const { t } = useTranslation('marketAuth');
|
|
115
|
+
const { styles } = useStyles();
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<Modal
|
|
119
|
+
cancelText={t('authorize.cancel')}
|
|
120
|
+
className={styles.content}
|
|
121
|
+
okButtonProps={{
|
|
122
|
+
className: styles.okButton,
|
|
123
|
+
icon: <ArrowRight size={16} />,
|
|
124
|
+
}}
|
|
125
|
+
okText={t('authorize.confirm')}
|
|
126
|
+
onCancel={onCancel}
|
|
127
|
+
onOk={onConfirm}
|
|
128
|
+
open={open}
|
|
129
|
+
title={null}
|
|
130
|
+
width={440}
|
|
131
|
+
>
|
|
132
|
+
<div className={styles.iconWrapper}>
|
|
133
|
+
<div className={styles.shieldIcon}>
|
|
134
|
+
<ShieldCheck />
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
<div className={styles.header}>
|
|
139
|
+
<div className={styles.title}>{t('authorize.title')}</div>
|
|
140
|
+
<div className={styles.description}>
|
|
141
|
+
{t('authorize.description.prefix')} <span className="highlight">LobeHub</span>{' '}
|
|
142
|
+
<a href="https://lobehub.com/terms" rel="noopener noreferrer" target="_blank">
|
|
143
|
+
{t('authorize.description.terms')}
|
|
144
|
+
</a>{' '}
|
|
145
|
+
{t('authorize.description.and')}{' '}
|
|
146
|
+
<a href="https://lobehub.com/privacy" rel="noopener noreferrer" target="_blank">
|
|
147
|
+
{t('authorize.description.privacy')}
|
|
148
|
+
</a>
|
|
149
|
+
</div>
|
|
150
|
+
</div>
|
|
151
|
+
</Modal>
|
|
152
|
+
);
|
|
153
|
+
},
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
MarketAuthConfirmModal.displayName = 'MarketAuthConfirmModal';
|
|
157
|
+
|
|
158
|
+
export default MarketAuthConfirmModal;
|