@lobehub/lobehub 2.0.0-next.27 → 2.0.0-next.29
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/package.json +1 -1
- package/packages/database/package.json +1 -1
- package/packages/database/src/models/message.ts +29 -2
- package/packages/types/src/discover/mcp.ts +6 -0
- package/packages/types/src/message/ui/params.ts +0 -49
- package/packages/types/src/plugins/mcp.ts +4 -1
- package/renovate.json +4 -30
- package/src/features/MCP/utils.test.ts +91 -0
- package/src/features/MCP/utils.ts +20 -2
- package/src/features/PluginStore/Content.tsx +2 -3
- package/src/features/PluginStore/McpList/index.tsx +6 -2
- package/src/server/routers/lambda/__tests__/integration/message.integration.test.ts +35 -35
- package/src/server/routers/lambda/market/index.ts +4 -2
- package/src/server/routers/lambda/message.ts +104 -16
- package/src/services/mcp.ts +40 -6
- package/src/services/message/index.ts +63 -35
- package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChat.test.ts +17 -10
- package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChatV2.test.ts +4 -4
- package/src/store/chat/slices/aiChat/actions/__tests__/helpers.ts +2 -2
- package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +3 -2
- package/src/store/chat/slices/aiChat/actions/generateAIChatV2.ts +2 -2
- package/src/store/chat/slices/aiChat/actions/generateAIGroupChat.ts +7 -2
- package/src/store/chat/slices/builtinTool/actions/search.ts +3 -3
- package/src/store/chat/slices/message/action.test.ts +152 -15
- package/src/store/chat/slices/message/action.ts +70 -82
- package/src/store/chat/slices/plugin/action.test.ts +84 -25
- package/src/store/chat/slices/plugin/action.ts +52 -24
- package/src/store/chat/slices/thread/action.test.ts +13 -4
- package/src/store/chat/slices/thread/action.ts +3 -1
- package/src/store/tool/slices/mcpStore/action.test.ts +95 -3
- package/src/store/tool/slices/mcpStore/action.ts +177 -53
- package/src/store/tool/slices/oldStore/initialState.ts +1 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 2.0.0-next.29](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.28...v2.0.0-next.29)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2025-11-04**</sup>
|
|
8
|
+
|
|
9
|
+
#### ♻ Code Refactoring
|
|
10
|
+
|
|
11
|
+
- **misc**: Refactor chat message model to speed up.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### Code refactoring
|
|
19
|
+
|
|
20
|
+
- **misc**: Refactor chat message model to speed up, closes [#10053](https://github.com/lobehub/lobe-chat/issues/10053) ([035994f](https://github.com/lobehub/lobe-chat/commit/035994f))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## [Version 2.0.0-next.28](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.27...v2.0.0-next.28)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2025-11-04**</sup>
|
|
33
|
+
|
|
34
|
+
#### ✨ Features
|
|
35
|
+
|
|
36
|
+
- **misc**: Support install sreamable http mcp server on web.
|
|
37
|
+
|
|
38
|
+
<br/>
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
42
|
+
|
|
43
|
+
#### What's improved
|
|
44
|
+
|
|
45
|
+
- **misc**: Support install sreamable http mcp server on web, closes [#10044](https://github.com/lobehub/lobe-chat/issues/10044) [#9916](https://github.com/lobehub/lobe-chat/issues/9916) ([85454c5](https://github.com/lobehub/lobe-chat/commit/85454c5))
|
|
46
|
+
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
<div align="right">
|
|
50
|
+
|
|
51
|
+
[](#readme-top)
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
5
55
|
## [Version 2.0.0-next.27](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.26...v2.0.0-next.27)
|
|
6
56
|
|
|
7
57
|
<sup>Released on **2025-11-04**</sup>
|
package/changelog/v1.json
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"children": {
|
|
4
|
+
"improvements": [
|
|
5
|
+
"Refactor chat message model to speed up."
|
|
6
|
+
]
|
|
7
|
+
},
|
|
8
|
+
"date": "2025-11-04",
|
|
9
|
+
"version": "2.0.0-next.29"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"children": {
|
|
13
|
+
"features": [
|
|
14
|
+
"Support install sreamable http mcp server on web."
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"date": "2025-11-04",
|
|
18
|
+
"version": "2.0.0-next.28"
|
|
19
|
+
},
|
|
2
20
|
{
|
|
3
21
|
"children": {
|
|
4
22
|
"improvements": [
|
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.29",
|
|
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",
|
|
@@ -603,6 +603,7 @@ export class MessageModel {
|
|
|
603
603
|
id: string,
|
|
604
604
|
{ imageList, ...message }: Partial<UpdateMessageParams>,
|
|
605
605
|
options?: {
|
|
606
|
+
groupAssistantMessages?: boolean;
|
|
606
607
|
postProcessUrl?: (path: string | null, file: { fileType: string }) => Promise<string>;
|
|
607
608
|
sessionId?: string | null;
|
|
608
609
|
topicId?: string | null;
|
|
@@ -633,6 +634,7 @@ export class MessageModel {
|
|
|
633
634
|
topicId: options.topicId,
|
|
634
635
|
},
|
|
635
636
|
{
|
|
637
|
+
groupAssistantMessages: options.groupAssistantMessages ?? false,
|
|
636
638
|
postProcessUrl: options.postProcessUrl,
|
|
637
639
|
},
|
|
638
640
|
);
|
|
@@ -660,16 +662,41 @@ export class MessageModel {
|
|
|
660
662
|
.where(and(eq(messages.userId, this.userId), eq(messages.id, id)));
|
|
661
663
|
};
|
|
662
664
|
|
|
663
|
-
updatePluginState = async (
|
|
665
|
+
updatePluginState = async (
|
|
666
|
+
id: string,
|
|
667
|
+
state: Record<string, any>,
|
|
668
|
+
options?: {
|
|
669
|
+
groupAssistantMessages?: boolean;
|
|
670
|
+
postProcessUrl?: (path: string | null, file: { fileType: string }) => Promise<string>;
|
|
671
|
+
sessionId?: string | null;
|
|
672
|
+
topicId?: string | null;
|
|
673
|
+
},
|
|
674
|
+
): Promise<UpdateMessageResult> => {
|
|
664
675
|
const item = await this.db.query.messagePlugins.findFirst({
|
|
665
676
|
where: eq(messagePlugins.id, id),
|
|
666
677
|
});
|
|
667
678
|
if (!item) throw new Error('Plugin not found');
|
|
668
679
|
|
|
669
|
-
|
|
680
|
+
await this.db
|
|
670
681
|
.update(messagePlugins)
|
|
671
682
|
.set({ state: merge(item.state || {}, state) })
|
|
672
683
|
.where(eq(messagePlugins.id, id));
|
|
684
|
+
|
|
685
|
+
// Return updated messages if sessionId or topicId is provided
|
|
686
|
+
if (options?.sessionId !== undefined || options?.topicId !== undefined) {
|
|
687
|
+
const messageList = await this.query(
|
|
688
|
+
{
|
|
689
|
+
sessionId: options.sessionId,
|
|
690
|
+
topicId: options.topicId,
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
groupAssistantMessages: options.groupAssistantMessages ?? false,
|
|
694
|
+
postProcessUrl: options.postProcessUrl,
|
|
695
|
+
},
|
|
696
|
+
);
|
|
697
|
+
return { messages: messageList, success: true };
|
|
698
|
+
}
|
|
699
|
+
return { success: true };
|
|
673
700
|
};
|
|
674
701
|
|
|
675
702
|
updateMessagePlugin = async (id: string, value: Partial<MessagePluginItem>) => {
|
|
@@ -39,10 +39,16 @@ export enum McpNavKey {
|
|
|
39
39
|
Version = 'version',
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
export enum McpConnectionType {
|
|
43
|
+
http = 'http',
|
|
44
|
+
stdio = 'stdio'
|
|
45
|
+
}
|
|
46
|
+
|
|
42
47
|
export type DiscoverMcpItem = PluginItem;
|
|
43
48
|
|
|
44
49
|
export interface McpQueryParams {
|
|
45
50
|
category?: string;
|
|
51
|
+
connectionType?: McpConnectionType;
|
|
46
52
|
locale?: string;
|
|
47
53
|
order?: 'asc' | 'desc';
|
|
48
54
|
page?: number;
|
|
@@ -120,55 +120,6 @@ const ChatPluginPayloadSchema = z.object({
|
|
|
120
120
|
type: z.string(),
|
|
121
121
|
});
|
|
122
122
|
|
|
123
|
-
export const CreateMessageParamsSchema = z
|
|
124
|
-
.object({
|
|
125
|
-
content: z.string(),
|
|
126
|
-
role: UIMessageRoleTypeSchema,
|
|
127
|
-
sessionId: z.string().nullable().optional(),
|
|
128
|
-
error: ChatMessageErrorSchema.nullable().optional(),
|
|
129
|
-
fileChunks: z.array(SemanticSearchChunkSchema).optional(),
|
|
130
|
-
files: z.array(z.string()).optional(),
|
|
131
|
-
fromModel: z.string().optional(),
|
|
132
|
-
fromProvider: z.string().optional(),
|
|
133
|
-
groupId: z.string().nullable().optional(),
|
|
134
|
-
targetId: z.string().nullable().optional(),
|
|
135
|
-
threadId: z.string().nullable().optional(),
|
|
136
|
-
topicId: z.string().nullable().optional(),
|
|
137
|
-
traceId: z.string().optional(),
|
|
138
|
-
// Allow additional fields from UIChatMessage (many can be null)
|
|
139
|
-
agentId: z.string().optional(),
|
|
140
|
-
children: z.any().optional(),
|
|
141
|
-
chunksList: z.any().optional(),
|
|
142
|
-
createdAt: z.number().optional(),
|
|
143
|
-
extra: z.any().optional(),
|
|
144
|
-
favorite: z.boolean().optional(),
|
|
145
|
-
fileList: z.any().optional(),
|
|
146
|
-
id: z.string().optional(),
|
|
147
|
-
imageList: z.any().optional(),
|
|
148
|
-
meta: z.any().optional(),
|
|
149
|
-
metadata: z.any().nullable().optional(),
|
|
150
|
-
model: z.string().nullable().optional(),
|
|
151
|
-
observationId: z.string().optional(),
|
|
152
|
-
parentId: z.string().optional(),
|
|
153
|
-
performance: z.any().optional(),
|
|
154
|
-
plugin: z.any().optional(),
|
|
155
|
-
pluginError: z.any().optional(),
|
|
156
|
-
pluginState: z.any().optional(),
|
|
157
|
-
provider: z.string().nullable().optional(),
|
|
158
|
-
quotaId: z.string().optional(),
|
|
159
|
-
ragQuery: z.string().nullable().optional(),
|
|
160
|
-
ragQueryId: z.string().nullable().optional(),
|
|
161
|
-
reasoning: z.any().optional(),
|
|
162
|
-
search: z.any().optional(),
|
|
163
|
-
tool_call_id: z.string().optional(),
|
|
164
|
-
toolCalls: z.any().optional(),
|
|
165
|
-
tools: z.any().optional(),
|
|
166
|
-
translate: z.any().optional(),
|
|
167
|
-
tts: z.any().optional(),
|
|
168
|
-
updatedAt: z.number().optional(),
|
|
169
|
-
})
|
|
170
|
-
.passthrough();
|
|
171
|
-
|
|
172
123
|
export const CreateNewMessageParamsSchema = z
|
|
173
124
|
.object({
|
|
174
125
|
// Required fields
|
|
@@ -3,6 +3,7 @@ import { z } from 'zod';
|
|
|
3
3
|
|
|
4
4
|
import { MCPErrorType } from '@/libs/mcp';
|
|
5
5
|
|
|
6
|
+
import { McpConnectionType } from '../discover/mcp';
|
|
6
7
|
import { CustomPluginMetadata } from '../tool/plugin';
|
|
7
8
|
|
|
8
9
|
/* eslint-disable typescript-sort-keys/string-enum */
|
|
@@ -110,7 +111,9 @@ export interface CheckMcpInstallResult {
|
|
|
110
111
|
}>;
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
export type MCPPluginListParams = Pick<PluginQueryParams, 'locale' | 'pageSize' | 'page' | 'q'
|
|
114
|
+
export type MCPPluginListParams = Pick<PluginQueryParams, 'locale' | 'pageSize' | 'page' | 'q'> & {
|
|
115
|
+
connectionType?: McpConnectionType;
|
|
116
|
+
};
|
|
114
117
|
|
|
115
118
|
export interface MCPErrorInfoMetadata {
|
|
116
119
|
errorLog?: string;
|
package/renovate.json
CHANGED
|
@@ -21,44 +21,18 @@
|
|
|
21
21
|
{
|
|
22
22
|
"description": "Isolate PRs for pinned deps (exact x.y.z)",
|
|
23
23
|
"matchManagers": ["npm", "pnpm", "yarn", "bun"],
|
|
24
|
-
"matchDepTypes": [
|
|
25
|
-
"dependencies",
|
|
26
|
-
"devDependencies",
|
|
27
|
-
"optionalDependencies",
|
|
28
|
-
"peerDependencies"
|
|
29
|
-
],
|
|
30
24
|
"matchCurrentValue": "^\\d+\\.\\d+\\.\\d+([+-][0-9A-Za-z.-]+)?$",
|
|
31
25
|
"groupName": null,
|
|
32
26
|
"separateMinorPatch": true,
|
|
33
27
|
"separateMajorMinor": true
|
|
34
28
|
},
|
|
35
|
-
//
|
|
29
|
+
// 2) Non-pinned deps: Patch versions, grouped together
|
|
36
30
|
{
|
|
37
|
-
"description": "
|
|
31
|
+
"description": "Group patch versions together for non-pinned deps",
|
|
38
32
|
"matchManagers": ["npm", "pnpm", "yarn", "bun"],
|
|
39
|
-
"matchDepTypes": [
|
|
40
|
-
"dependencies",
|
|
41
|
-
"devDependencies",
|
|
42
|
-
"optionalDependencies",
|
|
43
|
-
"peerDependencies"
|
|
44
|
-
],
|
|
45
33
|
"matchCurrentValue": "/(^[~^]|[<>=| -])/", // anything that looks like a range
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
},
|
|
49
|
-
// 2b) Non-pinned deps: actually group patch+minor together
|
|
50
|
-
{
|
|
51
|
-
"description": "Non-pinned deps: group non-major updates",
|
|
52
|
-
"matchManagers": ["npm", "pnpm", "yarn", "bun"],
|
|
53
|
-
"matchDepTypes": [
|
|
54
|
-
"dependencies",
|
|
55
|
-
"devDependencies",
|
|
56
|
-
"optionalDependencies",
|
|
57
|
-
"peerDependencies"
|
|
58
|
-
],
|
|
59
|
-
"matchCurrentValue": "/(^[~^]|[<>=| -])/",
|
|
60
|
-
"matchUpdateTypes": ["minor", "patch"], // only non-majors
|
|
61
|
-
"groupName": "deps (non-major)"
|
|
34
|
+
"groupName": "patch dependencies",
|
|
35
|
+
"matchUpdateTypes": ["patch"]
|
|
62
36
|
}
|
|
63
37
|
],
|
|
64
38
|
"postUpdateOptions": ["yarnDedupeHighest"],
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { genServerConfig } from './utils';
|
|
4
|
+
|
|
5
|
+
describe('genServerConfig', () => {
|
|
6
|
+
it('should generate HTTP MCP server config with url', () => {
|
|
7
|
+
const result = genServerConfig('context7', {
|
|
8
|
+
type: 'http',
|
|
9
|
+
url: 'https://mcp.context7.com/mcp',
|
|
10
|
+
} as any);
|
|
11
|
+
|
|
12
|
+
const config = JSON.parse(result);
|
|
13
|
+
|
|
14
|
+
expect(config).toEqual({
|
|
15
|
+
mcpServers: {
|
|
16
|
+
context7: {
|
|
17
|
+
url: 'https://mcp.context7.com/mcp',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should generate stdio MCP server config with command and args', () => {
|
|
24
|
+
const result = genServerConfig('github', {
|
|
25
|
+
args: ['-y', '@modelcontextprotocol/server-github'],
|
|
26
|
+
command: 'npx',
|
|
27
|
+
type: 'stdio',
|
|
28
|
+
} as any);
|
|
29
|
+
|
|
30
|
+
const config = JSON.parse(result);
|
|
31
|
+
|
|
32
|
+
expect(config).toEqual({
|
|
33
|
+
mcpServers: {
|
|
34
|
+
github: {
|
|
35
|
+
args: ['-y', '@modelcontextprotocol/server-github'],
|
|
36
|
+
command: 'npx',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should handle empty connection config', () => {
|
|
43
|
+
const result = genServerConfig('test-plugin', {} as any);
|
|
44
|
+
|
|
45
|
+
const config = JSON.parse(result);
|
|
46
|
+
|
|
47
|
+
expect(config).toEqual({
|
|
48
|
+
mcpServers: {
|
|
49
|
+
'test-plugin': {
|
|
50
|
+
args: [],
|
|
51
|
+
command: {},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should handle undefined connection', () => {
|
|
58
|
+
const result = genServerConfig('test-plugin', undefined);
|
|
59
|
+
|
|
60
|
+
const config = JSON.parse(result);
|
|
61
|
+
|
|
62
|
+
expect(config).toEqual({
|
|
63
|
+
mcpServers: {
|
|
64
|
+
'test-plugin': {
|
|
65
|
+
args: [],
|
|
66
|
+
command: {},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should prioritize url over command/args when both exist', () => {
|
|
73
|
+
const result = genServerConfig('hybrid', {
|
|
74
|
+
args: ['arg1'],
|
|
75
|
+
command: 'cmd',
|
|
76
|
+
type: 'http',
|
|
77
|
+
url: 'https://example.com/mcp',
|
|
78
|
+
} as any);
|
|
79
|
+
|
|
80
|
+
const config = JSON.parse(result);
|
|
81
|
+
|
|
82
|
+
// Should only include url, not command/args
|
|
83
|
+
expect(config).toEqual({
|
|
84
|
+
mcpServers: {
|
|
85
|
+
hybrid: {
|
|
86
|
+
url: 'https://example.com/mcp',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
import { ConnectionConfig, DeploymentOption } from '@lobehub/market-types';
|
|
2
2
|
|
|
3
|
-
export const genServerConfig = (identifier?: string, connection?: ConnectionConfig) =>
|
|
4
|
-
|
|
3
|
+
export const genServerConfig = (identifier?: string, connection?: ConnectionConfig) => {
|
|
4
|
+
// 检查是否为 HTTP 类型
|
|
5
|
+
if (connection?.url) {
|
|
6
|
+
// HTTP 类型配置
|
|
7
|
+
return JSON.stringify(
|
|
8
|
+
{
|
|
9
|
+
mcpServers: {
|
|
10
|
+
[String(identifier)]: {
|
|
11
|
+
url: connection.url,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
null,
|
|
16
|
+
2,
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// stdio 类型配置
|
|
21
|
+
return JSON.stringify(
|
|
5
22
|
{
|
|
6
23
|
mcpServers: {
|
|
7
24
|
[String(identifier)]: {
|
|
@@ -13,6 +30,7 @@ export const genServerConfig = (identifier?: string, connection?: ConnectionConf
|
|
|
13
30
|
null,
|
|
14
31
|
2,
|
|
15
32
|
);
|
|
33
|
+
};
|
|
16
34
|
|
|
17
35
|
export const getRecommendedDeployment = (deploymentOptions: DeploymentOption[]) =>
|
|
18
36
|
deploymentOptions?.find((item) => item.isRecommended) || deploymentOptions?.[0];
|
|
@@ -4,7 +4,6 @@ import { memo, useState } from 'react';
|
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
import { Flexbox } from 'react-layout-kit';
|
|
6
6
|
|
|
7
|
-
import { isDesktop } from '@/const/version';
|
|
8
7
|
import { useServerConfigStore } from '@/store/serverConfig';
|
|
9
8
|
import { useToolStore } from '@/store/tool';
|
|
10
9
|
import { PluginStoreTabs } from '@/store/tool/slices/oldStore';
|
|
@@ -22,7 +21,7 @@ export const Content = memo(() => {
|
|
|
22
21
|
const [keywords] = useState<string>();
|
|
23
22
|
|
|
24
23
|
const options = [
|
|
25
|
-
|
|
24
|
+
{ label: t('store.tabs.mcp'), value: PluginStoreTabs.MCP },
|
|
26
25
|
{ label: t('store.tabs.old'), value: PluginStoreTabs.Plugin },
|
|
27
26
|
{ label: t('store.tabs.installed'), value: PluginStoreTabs.Installed },
|
|
28
27
|
].filter(Boolean) as SegmentedOptions;
|
|
@@ -45,7 +44,7 @@ export const Content = memo(() => {
|
|
|
45
44
|
value={listType}
|
|
46
45
|
variant={'filled'}
|
|
47
46
|
/>
|
|
48
|
-
|
|
47
|
+
{mobile ? null : <AddPluginButton />}
|
|
49
48
|
</Flexbox>
|
|
50
49
|
<Search />
|
|
51
50
|
</Flexbox>
|
|
@@ -5,7 +5,7 @@ import { memo, useRef } from 'react';
|
|
|
5
5
|
import { Flexbox } from 'react-layout-kit';
|
|
6
6
|
|
|
7
7
|
import { useToolStore } from '@/store/tool';
|
|
8
|
-
|
|
8
|
+
import { useServerConfigStore } from '@/store/serverConfig';
|
|
9
9
|
import DetailLoading from './Detail/Loading';
|
|
10
10
|
import List from './List';
|
|
11
11
|
|
|
@@ -15,6 +15,8 @@ export const MCPPluginList = memo(() => {
|
|
|
15
15
|
const ref = useRef<HTMLDivElement>(null);
|
|
16
16
|
const theme = useTheme();
|
|
17
17
|
|
|
18
|
+
const mobile = useServerConfigStore((s) => s.isMobile);
|
|
19
|
+
|
|
18
20
|
return (
|
|
19
21
|
<Flexbox
|
|
20
22
|
height={'75vh'}
|
|
@@ -26,7 +28,9 @@ export const MCPPluginList = memo(() => {
|
|
|
26
28
|
}}
|
|
27
29
|
width={'100%'}
|
|
28
30
|
>
|
|
29
|
-
|
|
31
|
+
{/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}
|
|
32
|
+
{/* @ts-ignore */}
|
|
33
|
+
<DraggablePanel maxWidth={1024} minWidth={mobile ? '100vw' : 420} placement={'left'}>
|
|
30
34
|
<List
|
|
31
35
|
setIdentifier={(identifier) => {
|
|
32
36
|
useToolStore.setState({ activeMCPIdentifier: identifier });
|