@lobehub/lobehub 2.0.0-next.220 → 2.0.0-next.222
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/.github/workflows/claude-auto-testing.yml +6 -3
- package/.github/workflows/claude-dedupe-issues.yml +8 -1
- package/.github/workflows/claude-issue-triage.yml +8 -14
- package/.github/workflows/claude-translate-comments.yml +6 -3
- package/.github/workflows/claude-translator.yml +12 -14
- package/.github/workflows/claude.yml +10 -20
- package/.github/workflows/test.yml +26 -0
- package/.i18nrc.js +4 -2
- package/CHANGELOG.md +66 -0
- package/apps/desktop/src/main/core/browser/Browser.ts +48 -20
- package/apps/desktop/src/main/core/browser/__tests__/Browser.test.ts +1 -0
- package/changelog/v1.json +21 -0
- package/docs/glossary.md +11 -0
- package/locales/zh-CN/components.json +1 -0
- package/locales/zh-CN/topic.json +5 -5
- package/package.json +3 -3
- package/packages/const/src/index.ts +0 -1
- package/packages/memory-user-memory/package.json +1 -0
- package/packages/memory-user-memory/src/extractors/context.test.ts +3 -2
- package/packages/memory-user-memory/src/extractors/experience.test.ts +3 -2
- package/packages/memory-user-memory/src/extractors/identity.test.ts +23 -6
- package/packages/memory-user-memory/src/extractors/preference.test.ts +3 -2
- package/packages/memory-user-memory/vitest.config.ts +4 -0
- package/packages/model-runtime/src/providers/replicate/index.ts +1 -1
- package/packages/ssrf-safe-fetch/index.test.ts +2 -2
- package/packages/ssrf-safe-fetch/package.json +3 -2
- package/packages/types/src/serverConfig.ts +2 -0
- package/packages/utils/package.json +1 -1
- package/packages/utils/src/client/xor-obfuscation.test.ts +32 -32
- package/packages/utils/src/client/xor-obfuscation.ts +3 -4
- package/packages/utils/src/imageToBase64.ts +1 -1
- package/packages/utils/src/server/__tests__/auth.test.ts +1 -1
- package/packages/utils/src/server/auth.ts +1 -1
- package/packages/utils/src/server/xor.test.ts +9 -7
- package/packages/utils/src/server/xor.ts +1 -1
- package/packages/web-crawler/package.json +1 -1
- package/packages/web-crawler/src/crawImpl/__tests__/naive.test.ts +1 -1
- package/packages/web-crawler/src/crawImpl/naive.ts +1 -1
- package/scripts/prebuild.mts +58 -1
- package/src/app/(backend)/api/auth/[...all]/route.ts +2 -1
- package/src/app/(backend)/middleware/auth/index.ts +3 -3
- package/src/app/(backend)/middleware/auth/utils.test.ts +1 -1
- package/src/app/(backend)/middleware/auth/utils.ts +1 -1
- package/src/app/(backend)/webapi/chat/[provider]/route.test.ts +2 -2
- package/src/app/(backend)/webapi/models/[provider]/route.test.ts +1 -1
- package/src/app/(backend)/webapi/plugin/gateway/route.ts +1 -1
- package/src/app/(backend)/webapi/proxy/route.ts +1 -1
- package/src/app/[variants]/(auth)/login/[[...login]]/page.tsx +1 -1
- package/src/app/[variants]/(auth)/reset-password/layout.tsx +1 -1
- package/src/app/[variants]/(auth)/signin/layout.tsx +1 -1
- package/src/app/[variants]/(auth)/signin/useSignIn.ts +2 -2
- package/src/app/[variants]/(auth)/signup/[[...signup]]/page.tsx +1 -1
- package/src/app/[variants]/(auth)/signup/[[...signup]]/useSignUp.tsx +12 -6
- package/src/app/[variants]/(auth)/verify-email/layout.tsx +1 -1
- package/src/app/[variants]/(main)/settings/profile/features/AvatarRow.tsx +1 -1
- package/src/app/[variants]/(main)/settings/security/index.tsx +1 -1
- package/src/app/[variants]/(mobile)/me/(home)/__tests__/UserBanner.test.tsx +1 -1
- package/src/app/[variants]/(mobile)/me/(home)/__tests__/useCategory.test.tsx +1 -1
- package/src/app/[variants]/(mobile)/me/(home)/features/UserBanner.tsx +1 -1
- package/src/app/[variants]/(mobile)/settings/_layout/Header.tsx +1 -1
- package/src/components/ModelSelect/index.tsx +103 -72
- package/src/envs/auth.ts +30 -9
- package/src/features/Conversation/Messages/AssistantGroup/components/EditState.tsx +15 -32
- package/src/features/Conversation/Messages/AssistantGroup/index.tsx +9 -7
- package/src/features/EditorModal/EditorCanvas.tsx +31 -50
- package/src/features/EditorModal/TextareCanvas.tsx +3 -1
- package/src/features/EditorModal/index.tsx +14 -4
- package/src/features/ModelSwitchPanel/components/Footer.tsx +42 -0
- package/src/features/ModelSwitchPanel/components/List/MultipleProvidersModelItem.tsx +103 -0
- package/src/features/ModelSwitchPanel/components/List/SingleProviderModelItem.tsx +24 -0
- package/src/features/ModelSwitchPanel/components/List/VirtualItemRenderer.tsx +180 -0
- package/src/features/ModelSwitchPanel/components/List/index.tsx +99 -0
- package/src/features/ModelSwitchPanel/components/PanelContent.tsx +77 -0
- package/src/features/ModelSwitchPanel/components/Toolbar.tsx +54 -0
- package/src/features/ModelSwitchPanel/const.ts +29 -0
- package/src/features/ModelSwitchPanel/hooks/useBuildVirtualItems.ts +122 -0
- package/src/features/ModelSwitchPanel/hooks/useCurrentModelName.ts +18 -0
- package/src/features/ModelSwitchPanel/hooks/useDelayedRender.ts +18 -0
- package/src/features/ModelSwitchPanel/hooks/useModelAndProvider.ts +14 -0
- package/src/features/ModelSwitchPanel/hooks/usePanelHandlers.ts +33 -0
- package/src/features/ModelSwitchPanel/hooks/usePanelSize.ts +33 -0
- package/src/features/ModelSwitchPanel/hooks/usePanelState.ts +20 -0
- package/src/features/ModelSwitchPanel/index.tsx +25 -706
- package/src/features/ModelSwitchPanel/styles.ts +58 -0
- package/src/features/ModelSwitchPanel/types.ts +73 -0
- package/src/features/ModelSwitchPanel/utils.ts +24 -0
- package/src/features/User/UserPanel/PanelContent.tsx +1 -1
- package/src/features/User/__tests__/PanelContent.test.tsx +1 -1
- package/src/features/User/__tests__/UserAvatar.test.tsx +1 -1
- package/src/features/User/__tests__/useMenu.test.tsx +1 -1
- package/src/layout/GlobalProvider/StoreInitialization.tsx +2 -1
- package/src/libs/better-auth/auth-client.ts +7 -3
- package/src/libs/better-auth/define-config.ts +2 -2
- package/src/libs/next/proxy/define-config.ts +1 -2
- package/src/libs/oidc-provider/provider.test.ts +1 -1
- package/src/libs/trpc/async/context.ts +1 -1
- package/src/libs/trpc/lambda/context.ts +7 -8
- package/src/libs/trpc/middleware/userAuth.ts +1 -1
- package/src/libs/trusted-client/getSessionUser.ts +1 -1
- package/src/locales/default/components.ts +1 -0
- package/src/server/globalConfig/index.ts +2 -0
- package/src/server/routers/async/caller.ts +1 -1
- package/src/server/routers/lambda/__tests__/user.test.ts +2 -2
- package/src/server/routers/lambda/notebook.ts +4 -2
- package/src/server/routers/lambda/user.ts +2 -1
- package/src/services/_auth.ts +3 -3
- package/src/services/chat/index.ts +1 -1
- package/src/services/chat/mecha/contextEngineering.ts +1 -1
- package/src/services/notebook.ts +2 -0
- package/src/store/global/initialState.ts +10 -0
- package/src/store/global/selectors/systemStatus.ts +5 -0
- package/src/store/serverConfig/selectors.ts +5 -1
- package/src/store/tool/slices/builtin/executors/lobe-web-browsing.ts +2 -0
- package/src/store/tool/slices/mcpStore/action.ts +74 -75
- package/src/store/user/slices/auth/action.test.ts +1 -1
- package/src/store/user/slices/auth/action.ts +1 -1
- package/src/store/user/slices/auth/initialState.ts +1 -1
- package/src/store/user/slices/auth/selectors.test.ts +1 -1
- package/src/store/user/slices/auth/selectors.ts +1 -1
- package/src/store/user/slices/common/action.ts +1 -1
- package/src/store/userMemory/slices/context/action.ts +6 -6
- package/glossary.json +0 -8
- package/packages/const/src/auth.ts +0 -14
|
@@ -67,7 +67,6 @@ const toNonEmptyStringRecord = (input?: Record<string, any>) => {
|
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
69
|
* Build manifest for cloud MCP connection from market data
|
|
70
|
-
* 从市场数据构建 Cloud MCP 的 manifest
|
|
71
70
|
*/
|
|
72
71
|
const buildCloudMcpManifest = (params: {
|
|
73
72
|
data: any;
|
|
@@ -77,21 +76,21 @@ const buildCloudMcpManifest = (params: {
|
|
|
77
76
|
|
|
78
77
|
log('Using cloud connection, building manifest from market data');
|
|
79
78
|
|
|
80
|
-
//
|
|
79
|
+
// Get tools (MCP format) or api (LobeChat format) from data
|
|
81
80
|
const mcpTools = data.tools;
|
|
82
81
|
const lobeChatApi = data.api;
|
|
83
82
|
|
|
84
|
-
//
|
|
83
|
+
// If MCP format tools, need to convert to LobeChat api format
|
|
85
84
|
// MCP: { name, description, inputSchema }
|
|
86
85
|
// LobeChat: { name, description, parameters }
|
|
87
86
|
let apiArray: any[] = [];
|
|
88
87
|
|
|
89
88
|
if (lobeChatApi) {
|
|
90
|
-
//
|
|
89
|
+
// Already in LobeChat format, use directly
|
|
91
90
|
apiArray = lobeChatApi;
|
|
92
91
|
log('[Cloud MCP] Using existing LobeChat API format');
|
|
93
92
|
} else if (mcpTools && Array.isArray(mcpTools)) {
|
|
94
|
-
//
|
|
93
|
+
// Convert MCP tools format to LobeChat api format
|
|
95
94
|
apiArray = mcpTools.map((tool: any) => ({
|
|
96
95
|
description: tool.description || '',
|
|
97
96
|
name: tool.name,
|
|
@@ -102,7 +101,7 @@ const buildCloudMcpManifest = (params: {
|
|
|
102
101
|
console.warn('[Cloud MCP] No tools or api found in manifest data');
|
|
103
102
|
}
|
|
104
103
|
|
|
105
|
-
//
|
|
104
|
+
// Build complete manifest
|
|
106
105
|
const manifest: LobeChatPluginManifest = {
|
|
107
106
|
api: apiArray,
|
|
108
107
|
author: data.author?.name || data.author || '',
|
|
@@ -130,7 +129,7 @@ const buildCloudMcpManifest = (params: {
|
|
|
130
129
|
return manifest;
|
|
131
130
|
};
|
|
132
131
|
|
|
133
|
-
//
|
|
132
|
+
// Test connection result type
|
|
134
133
|
export interface TestMcpConnectionResult {
|
|
135
134
|
error?: string;
|
|
136
135
|
manifest?: LobeChatPluginManifest;
|
|
@@ -146,7 +145,7 @@ export interface PluginMCPStoreAction {
|
|
|
146
145
|
) => Promise<boolean | undefined>;
|
|
147
146
|
loadMoreMCPPlugins: () => void;
|
|
148
147
|
resetMCPPluginList: (keywords?: string) => void;
|
|
149
|
-
//
|
|
148
|
+
// Test connection related methods
|
|
150
149
|
testMcpConnection: (params: McpConnectionParams) => Promise<TestMcpConnectionResult>;
|
|
151
150
|
uninstallMCPPlugin: (identifier: string) => Promise<void>;
|
|
152
151
|
updateMCPInstallProgress: (identifier: string, progress: MCPInstallProgress | undefined) => void;
|
|
@@ -160,12 +159,12 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
160
159
|
PluginMCPStoreAction
|
|
161
160
|
> = (set, get) => ({
|
|
162
161
|
cancelInstallMCPPlugin: async (identifier) => {
|
|
163
|
-
//
|
|
162
|
+
// Get and cancel AbortController
|
|
164
163
|
const abortController = get().mcpInstallAbortControllers[identifier];
|
|
165
164
|
if (abortController) {
|
|
166
165
|
abortController.abort();
|
|
167
166
|
|
|
168
|
-
//
|
|
167
|
+
// Clean up AbortController storage
|
|
169
168
|
set(
|
|
170
169
|
produce((draft: MCPStoreState) => {
|
|
171
170
|
delete draft.mcpInstallAbortControllers[identifier];
|
|
@@ -175,18 +174,18 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
175
174
|
);
|
|
176
175
|
}
|
|
177
176
|
|
|
178
|
-
//
|
|
177
|
+
// Clean up installation progress and loading state
|
|
179
178
|
get().updateMCPInstallProgress(identifier, undefined);
|
|
180
179
|
get().updateInstallLoadingState(identifier, undefined);
|
|
181
180
|
},
|
|
182
181
|
|
|
183
|
-
//
|
|
182
|
+
// Cancel MCP connection test
|
|
184
183
|
cancelMcpConnectionTest: (identifier) => {
|
|
185
184
|
const abortController = get().mcpTestAbortControllers[identifier];
|
|
186
185
|
if (abortController) {
|
|
187
186
|
abortController.abort();
|
|
188
187
|
|
|
189
|
-
//
|
|
188
|
+
// Clean up state
|
|
190
189
|
set(
|
|
191
190
|
produce((draft: MCPStoreState) => {
|
|
192
191
|
draft.mcpTestLoading[identifier] = false;
|
|
@@ -218,10 +217,10 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
218
217
|
|
|
219
218
|
const { updateInstallLoadingState, refreshPlugins, updateMCPInstallProgress } = get();
|
|
220
219
|
|
|
221
|
-
//
|
|
220
|
+
// Create AbortController for canceling installation
|
|
222
221
|
const abortController = new AbortController();
|
|
223
222
|
|
|
224
|
-
//
|
|
223
|
+
// Store AbortController
|
|
225
224
|
set(
|
|
226
225
|
produce((draft: MCPStoreState) => {
|
|
227
226
|
draft.mcpInstallAbortControllers[identifier] = abortController;
|
|
@@ -230,7 +229,7 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
230
229
|
n('installMCPPlugin/setController'),
|
|
231
230
|
);
|
|
232
231
|
|
|
233
|
-
//
|
|
232
|
+
// Record installation start time
|
|
234
233
|
const installStartTime = Date.now();
|
|
235
234
|
|
|
236
235
|
let data: any;
|
|
@@ -239,13 +238,13 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
239
238
|
const userAgent = `LobeHub Desktop/${CURRENT_VERSION}`;
|
|
240
239
|
|
|
241
240
|
try {
|
|
242
|
-
//
|
|
241
|
+
// Check if already cancelled
|
|
243
242
|
if (abortController.signal.aborted) {
|
|
244
243
|
return;
|
|
245
244
|
}
|
|
246
245
|
|
|
247
246
|
if (resume) {
|
|
248
|
-
//
|
|
247
|
+
// Resume mode: get previous info from storage
|
|
249
248
|
const configInfo = get().mcpInstallProgress[identifier];
|
|
250
249
|
if (!configInfo) {
|
|
251
250
|
console.error('No config info found for resume');
|
|
@@ -256,9 +255,9 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
256
255
|
connection = configInfo.connection ? { ...configInfo.connection } : undefined;
|
|
257
256
|
result = configInfo.checkResult;
|
|
258
257
|
} else {
|
|
259
|
-
//
|
|
258
|
+
// Normal mode: start installation from scratch
|
|
260
259
|
|
|
261
|
-
//
|
|
260
|
+
// Step 1: Fetch plugin manifest
|
|
262
261
|
updateMCPInstallProgress(identifier, {
|
|
263
262
|
progress: 15,
|
|
264
263
|
step: MCPInstallStep.FETCHING_MANIFEST,
|
|
@@ -266,7 +265,7 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
266
265
|
|
|
267
266
|
updateInstallLoadingState(identifier, true);
|
|
268
267
|
|
|
269
|
-
//
|
|
268
|
+
// Check if already cancelled
|
|
270
269
|
if (abortController.signal.aborted) {
|
|
271
270
|
return;
|
|
272
271
|
}
|
|
@@ -285,7 +284,7 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
285
284
|
) ||
|
|
286
285
|
deploymentOptions.find((option) => option?.connection?.url && !option?.connection?.type);
|
|
287
286
|
|
|
288
|
-
//
|
|
287
|
+
// Find stdio type deployment option
|
|
289
288
|
const stdioOption = deploymentOptions.find(
|
|
290
289
|
(option) =>
|
|
291
290
|
option?.connection?.type === 'stdio' ||
|
|
@@ -299,7 +298,7 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
299
298
|
return type && type !== 'http';
|
|
300
299
|
});
|
|
301
300
|
|
|
302
|
-
//
|
|
301
|
+
// Check if cloudEndPoint is available: web + stdio type + haveCloudEndpoint exists
|
|
303
302
|
const hasCloudEndpoint = !isDesktop && stdioOption && haveCloudEndpoint;
|
|
304
303
|
|
|
305
304
|
console.log('hasCloudEndpoint', hasCloudEndpoint);
|
|
@@ -307,7 +306,7 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
307
306
|
let shouldUseHttpDeployment = !!httpOption && (!hasNonHttpDeployment || !isDesktop);
|
|
308
307
|
|
|
309
308
|
if (hasCloudEndpoint) {
|
|
310
|
-
//
|
|
309
|
+
// Use cloudEndPoint, create cloud type connection
|
|
311
310
|
log('Using cloudEndPoint for stdio plugin: %s', haveCloudEndpoint);
|
|
312
311
|
|
|
313
312
|
connection = {
|
|
@@ -339,7 +338,7 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
339
338
|
return false;
|
|
340
339
|
}
|
|
341
340
|
} else if (shouldUseHttpDeployment && httpOption) {
|
|
342
|
-
//
|
|
341
|
+
// HTTP type: skip system dependency check, use URL directly
|
|
343
342
|
log('HTTP MCP detected, skipping system dependency check');
|
|
344
343
|
|
|
345
344
|
connection = {
|
|
@@ -368,15 +367,15 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
368
367
|
return false;
|
|
369
368
|
}
|
|
370
369
|
} else {
|
|
371
|
-
//
|
|
370
|
+
// stdio type: requires complete system dependency check process
|
|
372
371
|
|
|
373
|
-
//
|
|
372
|
+
// Step 2: Check installation environment
|
|
374
373
|
updateMCPInstallProgress(identifier, {
|
|
375
374
|
progress: 30,
|
|
376
375
|
step: MCPInstallStep.CHECKING_INSTALLATION,
|
|
377
376
|
});
|
|
378
377
|
|
|
379
|
-
//
|
|
378
|
+
// Check if already cancelled
|
|
380
379
|
if (abortController.signal.aborted) {
|
|
381
380
|
return;
|
|
382
381
|
}
|
|
@@ -388,9 +387,9 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
388
387
|
return;
|
|
389
388
|
}
|
|
390
389
|
|
|
391
|
-
//
|
|
390
|
+
// Step 3: Check if system dependencies are met
|
|
392
391
|
if (!skipDepsCheck && !result.allDependenciesMet) {
|
|
393
|
-
//
|
|
392
|
+
// Dependencies not met, pause installation and show dependency installation guide
|
|
394
393
|
updateMCPInstallProgress(identifier, {
|
|
395
394
|
connection: result.connection,
|
|
396
395
|
manifest: data,
|
|
@@ -399,14 +398,14 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
399
398
|
systemDependencies: result.systemDependencies,
|
|
400
399
|
});
|
|
401
400
|
|
|
402
|
-
//
|
|
401
|
+
// Pause installation, wait for user to install dependencies
|
|
403
402
|
updateInstallLoadingState(identifier, undefined);
|
|
404
|
-
return false; //
|
|
403
|
+
return false; // Return false to indicate dependencies need to be installed
|
|
405
404
|
}
|
|
406
405
|
|
|
407
|
-
//
|
|
406
|
+
// Step 4: Check if configuration is needed
|
|
408
407
|
if (result.needsConfig) {
|
|
409
|
-
//
|
|
408
|
+
// Configuration needed, pause installation
|
|
410
409
|
updateMCPInstallProgress(identifier, {
|
|
411
410
|
checkResult: result,
|
|
412
411
|
configSchema: result.configSchema,
|
|
@@ -417,9 +416,9 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
417
416
|
step: MCPInstallStep.CONFIGURATION_REQUIRED,
|
|
418
417
|
});
|
|
419
418
|
|
|
420
|
-
//
|
|
419
|
+
// Pause installation, wait for user configuration
|
|
421
420
|
updateInstallLoadingState(identifier, undefined);
|
|
422
|
-
return false; //
|
|
421
|
+
return false; // Return false to indicate configuration is needed
|
|
423
422
|
}
|
|
424
423
|
|
|
425
424
|
connection = result.connection;
|
|
@@ -463,16 +462,16 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
463
462
|
}
|
|
464
463
|
}
|
|
465
464
|
|
|
466
|
-
//
|
|
465
|
+
// Get server manifest logic
|
|
467
466
|
updateInstallLoadingState(identifier, true);
|
|
468
467
|
|
|
469
|
-
//
|
|
468
|
+
// Step 5: Get server manifest
|
|
470
469
|
updateMCPInstallProgress(identifier, {
|
|
471
470
|
progress: 70,
|
|
472
471
|
step: MCPInstallStep.GETTING_SERVER_MANIFEST,
|
|
473
472
|
});
|
|
474
473
|
|
|
475
|
-
//
|
|
474
|
+
// Check if already cancelled
|
|
476
475
|
if (abortController.signal.aborted) {
|
|
477
476
|
return;
|
|
478
477
|
}
|
|
@@ -485,7 +484,7 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
485
484
|
args: connection.args,
|
|
486
485
|
command: connection.command!,
|
|
487
486
|
env: mergedStdioEnv,
|
|
488
|
-
name: identifier, //
|
|
487
|
+
name: identifier, // Pass config as environment variables (in resume mode)
|
|
489
488
|
},
|
|
490
489
|
{ avatar: plugin.icon, description: plugin.description, name: data.name },
|
|
491
490
|
abortController.signal,
|
|
@@ -507,31 +506,31 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
507
506
|
);
|
|
508
507
|
}
|
|
509
508
|
if (connection?.type === 'cloud') {
|
|
510
|
-
//
|
|
509
|
+
// Cloud type: build manifest directly from market data
|
|
511
510
|
manifest = buildCloudMcpManifest({ data, plugin });
|
|
512
511
|
}
|
|
513
512
|
|
|
514
513
|
// set version
|
|
515
514
|
if (manifest) {
|
|
516
|
-
// set Version -
|
|
515
|
+
// set Version - use semver to compare versions and take the larger value
|
|
517
516
|
const dataVersion = data?.version;
|
|
518
517
|
const manifestVersion = manifest.version;
|
|
519
518
|
|
|
520
519
|
if (dataVersion && manifestVersion) {
|
|
521
|
-
//
|
|
520
|
+
// If both versions exist, compare and take the larger value
|
|
522
521
|
if (valid(dataVersion) && valid(manifestVersion)) {
|
|
523
522
|
manifest.version = gt(dataVersion, manifestVersion) ? dataVersion : manifestVersion;
|
|
524
523
|
} else {
|
|
525
|
-
//
|
|
524
|
+
// If version format is incorrect, prioritize dataVersion
|
|
526
525
|
manifest.version = dataVersion;
|
|
527
526
|
}
|
|
528
527
|
} else {
|
|
529
|
-
//
|
|
528
|
+
// If only one version exists, use the existing version
|
|
530
529
|
manifest.version = dataVersion || manifestVersion;
|
|
531
530
|
}
|
|
532
531
|
}
|
|
533
532
|
|
|
534
|
-
//
|
|
533
|
+
// Check if already cancelled
|
|
535
534
|
if (abortController.signal.aborted) {
|
|
536
535
|
return;
|
|
537
536
|
}
|
|
@@ -541,18 +540,18 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
541
540
|
return;
|
|
542
541
|
}
|
|
543
542
|
|
|
544
|
-
//
|
|
543
|
+
// Step 6: Install plugin
|
|
545
544
|
updateMCPInstallProgress(identifier, {
|
|
546
545
|
progress: 90,
|
|
547
546
|
step: MCPInstallStep.INSTALLING_PLUGIN,
|
|
548
547
|
});
|
|
549
548
|
|
|
550
|
-
//
|
|
549
|
+
// Check if already cancelled
|
|
551
550
|
if (abortController.signal.aborted) {
|
|
552
551
|
return;
|
|
553
552
|
}
|
|
554
553
|
|
|
555
|
-
//
|
|
554
|
+
// Update connection object, write merged configuration
|
|
556
555
|
const finalConnection = { ...connection };
|
|
557
556
|
if (finalConnection.type === 'http' && mergedHttpHeaders) {
|
|
558
557
|
finalConnection.headers = mergedHttpHeaders;
|
|
@@ -565,7 +564,7 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
565
564
|
}
|
|
566
565
|
|
|
567
566
|
await pluginService.installPlugin({
|
|
568
|
-
//
|
|
567
|
+
// For mcp, store connection info in customParams field first
|
|
569
568
|
customParams: { mcp: finalConnection },
|
|
570
569
|
identifier: plugin.identifier,
|
|
571
570
|
manifest: manifest,
|
|
@@ -573,20 +572,20 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
573
572
|
type: 'plugin',
|
|
574
573
|
});
|
|
575
574
|
|
|
576
|
-
//
|
|
575
|
+
// Check if already cancelled
|
|
577
576
|
if (abortController.signal.aborted) {
|
|
578
577
|
return;
|
|
579
578
|
}
|
|
580
579
|
|
|
581
580
|
await refreshPlugins();
|
|
582
581
|
|
|
583
|
-
//
|
|
582
|
+
// Step 7: Complete installation
|
|
584
583
|
updateMCPInstallProgress(identifier, {
|
|
585
584
|
progress: 100,
|
|
586
585
|
step: MCPInstallStep.COMPLETED,
|
|
587
586
|
});
|
|
588
587
|
|
|
589
|
-
//
|
|
588
|
+
// Calculate installation duration
|
|
590
589
|
const installDurationMs = Date.now() - installStartTime;
|
|
591
590
|
|
|
592
591
|
discoverService.reportMcpInstallResult({
|
|
@@ -604,13 +603,13 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
604
603
|
version: manifest.version || data.version,
|
|
605
604
|
});
|
|
606
605
|
|
|
607
|
-
//
|
|
606
|
+
// Show completed status briefly then clear progress
|
|
608
607
|
await sleep(1000);
|
|
609
608
|
|
|
610
609
|
updateMCPInstallProgress(identifier, undefined);
|
|
611
610
|
updateInstallLoadingState(identifier, undefined);
|
|
612
611
|
|
|
613
|
-
//
|
|
612
|
+
// Clean up AbortController
|
|
614
613
|
set(
|
|
615
614
|
produce((draft: MCPStoreState) => {
|
|
616
615
|
delete draft.mcpInstallAbortControllers[identifier];
|
|
@@ -621,7 +620,7 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
621
620
|
|
|
622
621
|
return true;
|
|
623
622
|
} catch (e) {
|
|
624
|
-
//
|
|
623
|
+
// Silently handle errors caused by cancellation
|
|
625
624
|
if (abortController.signal.aborted) {
|
|
626
625
|
console.log('MCP plugin installation cancelled for:', identifier);
|
|
627
626
|
return;
|
|
@@ -631,13 +630,13 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
631
630
|
|
|
632
631
|
console.error('MCP plugin installation failed:', error);
|
|
633
632
|
|
|
634
|
-
//
|
|
633
|
+
// Calculate installation duration (failure case)
|
|
635
634
|
const installDurationMs = Date.now() - installStartTime;
|
|
636
635
|
|
|
637
|
-
//
|
|
636
|
+
// Handle structured error info
|
|
638
637
|
let errorInfo: MCPErrorInfo;
|
|
639
638
|
|
|
640
|
-
//
|
|
639
|
+
// If it's a structured MCPError
|
|
641
640
|
if (!!error.data && 'errorData' in error.data) {
|
|
642
641
|
const mcpError = error.data.errorData as MCPErrorData;
|
|
643
642
|
|
|
@@ -647,7 +646,7 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
647
646
|
type: mcpError.type,
|
|
648
647
|
};
|
|
649
648
|
} else {
|
|
650
|
-
//
|
|
649
|
+
// Fallback handling for normal errors
|
|
651
650
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
652
651
|
errorInfo = {
|
|
653
652
|
message: errorMessage,
|
|
@@ -659,14 +658,14 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
659
658
|
};
|
|
660
659
|
}
|
|
661
660
|
|
|
662
|
-
//
|
|
661
|
+
// Set error status, display structured error info
|
|
663
662
|
updateMCPInstallProgress(identifier, {
|
|
664
663
|
errorInfo,
|
|
665
664
|
progress: 0,
|
|
666
665
|
step: MCPInstallStep.ERROR,
|
|
667
666
|
});
|
|
668
667
|
|
|
669
|
-
//
|
|
668
|
+
// Report installation failure result
|
|
670
669
|
discoverService.reportMcpInstallResult({
|
|
671
670
|
errorCode: errorInfo.type,
|
|
672
671
|
errorMessage: errorInfo.message,
|
|
@@ -682,7 +681,7 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
682
681
|
|
|
683
682
|
updateInstallLoadingState(identifier, undefined);
|
|
684
683
|
|
|
685
|
-
//
|
|
684
|
+
// Clean up AbortController
|
|
686
685
|
set(
|
|
687
686
|
produce((draft: MCPStoreState) => {
|
|
688
687
|
delete draft.mcpInstallAbortControllers[identifier];
|
|
@@ -696,7 +695,7 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
696
695
|
loadMoreMCPPlugins: () => {
|
|
697
696
|
const { mcpPluginItems, totalCount, currentPage } = get();
|
|
698
697
|
|
|
699
|
-
//
|
|
698
|
+
// Check if there's more data to load
|
|
700
699
|
if (mcpPluginItems.length < (totalCount || 0)) {
|
|
701
700
|
set(
|
|
702
701
|
produce((draft: MCPStoreState) => {
|
|
@@ -720,14 +719,14 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
720
719
|
);
|
|
721
720
|
},
|
|
722
721
|
|
|
723
|
-
//
|
|
722
|
+
// Test MCP connection
|
|
724
723
|
testMcpConnection: async (params) => {
|
|
725
724
|
const { identifier, connection, metadata } = params;
|
|
726
725
|
|
|
727
|
-
//
|
|
726
|
+
// Create AbortController for canceling test
|
|
728
727
|
const abortController = new AbortController();
|
|
729
728
|
|
|
730
|
-
//
|
|
729
|
+
// Store AbortController and set loading state
|
|
731
730
|
set(
|
|
732
731
|
produce((draft: MCPStoreState) => {
|
|
733
732
|
draft.mcpTestAbortControllers[identifier] = abortController;
|
|
@@ -775,12 +774,12 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
775
774
|
throw new Error('Invalid MCP connection type');
|
|
776
775
|
}
|
|
777
776
|
|
|
778
|
-
//
|
|
777
|
+
// Check if already cancelled
|
|
779
778
|
if (abortController.signal.aborted) {
|
|
780
779
|
return { error: 'Test cancelled', success: false };
|
|
781
780
|
}
|
|
782
781
|
|
|
783
|
-
//
|
|
782
|
+
// Clean up state
|
|
784
783
|
set(
|
|
785
784
|
produce((draft: MCPStoreState) => {
|
|
786
785
|
draft.mcpTestLoading[identifier] = false;
|
|
@@ -793,14 +792,14 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
793
792
|
|
|
794
793
|
return { manifest, success: true };
|
|
795
794
|
} catch (error) {
|
|
796
|
-
//
|
|
795
|
+
// Silently handle errors caused by cancellation
|
|
797
796
|
if (abortController.signal.aborted) {
|
|
798
797
|
return { error: 'Test cancelled', success: false };
|
|
799
798
|
}
|
|
800
799
|
|
|
801
800
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
802
801
|
|
|
803
|
-
//
|
|
802
|
+
// Set error state
|
|
804
803
|
set(
|
|
805
804
|
produce((draft: MCPStoreState) => {
|
|
806
805
|
draft.mcpTestLoading[identifier] = false;
|
|
@@ -857,7 +856,7 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
857
856
|
produce((draft: MCPStoreState) => {
|
|
858
857
|
draft.searchLoading = false;
|
|
859
858
|
|
|
860
|
-
//
|
|
859
|
+
// Set basic information
|
|
861
860
|
if (!draft.isMcpListInit) {
|
|
862
861
|
draft.activeMCPIdentifier = data.items?.[0]?.identifier;
|
|
863
862
|
|
|
@@ -867,12 +866,12 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
867
866
|
draft.totalPages = data.totalPages;
|
|
868
867
|
}
|
|
869
868
|
|
|
870
|
-
//
|
|
869
|
+
// Accumulate data logic
|
|
871
870
|
if (page === 1) {
|
|
872
|
-
//
|
|
871
|
+
// First page, set directly
|
|
873
872
|
draft.mcpPluginItems = uniqBy(data.items, 'identifier');
|
|
874
873
|
} else {
|
|
875
|
-
//
|
|
874
|
+
// Subsequent pages, accumulate data
|
|
876
875
|
draft.mcpPluginItems = uniqBy(
|
|
877
876
|
[...draft.mcpPluginItems, ...data.items],
|
|
878
877
|
'identifier',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type SSOProvider } from '@lobechat/types';
|
|
2
2
|
import { type StateCreator } from 'zustand/vanilla';
|
|
3
3
|
|
|
4
|
-
import { enableAuth, enableBetterAuth, enableClerk, enableNextAuth } from '@/
|
|
4
|
+
import { enableAuth, enableBetterAuth, enableClerk, enableNextAuth } from '@/envs/auth';
|
|
5
5
|
import { userService } from '@/services/user';
|
|
6
6
|
|
|
7
7
|
import type { UserStore } from '../../store';
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from '@clerk/types';
|
|
9
9
|
import { type SSOProvider } from '@lobechat/types';
|
|
10
10
|
|
|
11
|
-
import { enableClerk } from '@/
|
|
11
|
+
import { enableClerk } from '@/envs/auth';
|
|
12
12
|
import { type LobeUser } from '@/types/user';
|
|
13
13
|
|
|
14
14
|
export interface UserAuthState {
|
|
@@ -3,7 +3,7 @@ import { isDesktop } from '@lobechat/const';
|
|
|
3
3
|
import { type LobeUser, type SSOProvider } from '@lobechat/types';
|
|
4
4
|
import { t } from 'i18next';
|
|
5
5
|
|
|
6
|
-
import { enableAuth, enableBetterAuth, enableClerk, enableNextAuth } from '@/
|
|
6
|
+
import { enableAuth, enableBetterAuth, enableClerk, enableNextAuth } from '@/envs/auth';
|
|
7
7
|
import type { UserStore } from '@/store/user';
|
|
8
8
|
|
|
9
9
|
const DEFAULT_USERNAME = BRANDING_NAME;
|
|
@@ -91,29 +91,29 @@ export const createContextSlice: StateCreator<
|
|
|
91
91
|
produce((draft) => {
|
|
92
92
|
draft.contextsSearchLoading = false;
|
|
93
93
|
|
|
94
|
-
//
|
|
94
|
+
// Set basic information
|
|
95
95
|
if (!draft.contextsInit) {
|
|
96
96
|
draft.contextsInit = true;
|
|
97
97
|
draft.contextsTotal = data.total;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
//
|
|
100
|
+
// Transform data structure
|
|
101
101
|
const transformedItems = data.items.map((item: any) => ({
|
|
102
102
|
...item.memory,
|
|
103
103
|
...item.context,
|
|
104
104
|
source: null,
|
|
105
105
|
}));
|
|
106
106
|
|
|
107
|
-
//
|
|
107
|
+
// Accumulate data logic
|
|
108
108
|
if (page === 1) {
|
|
109
|
-
//
|
|
109
|
+
// First page, set directly
|
|
110
110
|
draft.contexts = uniqBy(transformedItems, 'id');
|
|
111
111
|
} else {
|
|
112
|
-
//
|
|
112
|
+
// Subsequent pages, accumulate data
|
|
113
113
|
draft.contexts = uniqBy([...draft.contexts, ...transformedItems], 'id');
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
//
|
|
116
|
+
// Update hasMore
|
|
117
117
|
draft.contextsHasMore = data.items.length >= (params.pageSize || 20);
|
|
118
118
|
}),
|
|
119
119
|
false,
|
package/glossary.json
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export const enableClerk =
|
|
2
|
-
process.env.NEXT_PUBLIC_ENABLE_CLERK_AUTH === '1'
|
|
3
|
-
? true
|
|
4
|
-
: !!process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY;
|
|
5
|
-
export const enableBetterAuth = process.env.NEXT_PUBLIC_ENABLE_BETTER_AUTH === '1';
|
|
6
|
-
export const enableNextAuth = process.env.NEXT_PUBLIC_ENABLE_NEXT_AUTH === '1';
|
|
7
|
-
export const enableAuth = enableClerk || enableBetterAuth || enableNextAuth || false;
|
|
8
|
-
|
|
9
|
-
export const LOBE_CHAT_AUTH_HEADER = 'X-lobe-chat-auth';
|
|
10
|
-
export const LOBE_CHAT_OIDC_AUTH_HEADER = 'Oidc-Auth';
|
|
11
|
-
|
|
12
|
-
export const OAUTH_AUTHORIZED = 'X-oauth-authorized';
|
|
13
|
-
|
|
14
|
-
export const SECRET_XOR_KEY = 'LobeHub · LobeHub';
|