@lobehub/chat 1.109.0 → 1.110.0

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.
Files changed (100) hide show
  1. package/.cursor/rules/i18n.mdc +1 -2
  2. package/CHANGELOG.md +59 -0
  3. package/README.md +1 -1
  4. package/README.zh-CN.md +1 -1
  5. package/apps/desktop/electron-builder.js +22 -0
  6. package/apps/desktop/src/main/controllers/McpInstallCtr.ts +153 -0
  7. package/apps/desktop/src/main/controllers/index.ts +19 -0
  8. package/apps/desktop/src/main/core/App.ts +46 -0
  9. package/apps/desktop/src/main/core/infrastructure/IoCContainer.ts +4 -0
  10. package/apps/desktop/src/main/core/infrastructure/ProtocolManager.ts +256 -0
  11. package/apps/desktop/src/main/types/protocol.ts +60 -0
  12. package/apps/desktop/src/main/utils/__tests__/protocol.test.ts +203 -0
  13. package/apps/desktop/src/main/utils/protocol.ts +210 -0
  14. package/changelog/v1.json +21 -0
  15. package/locales/ar/models.json +6 -0
  16. package/locales/ar/plugin.json +196 -136
  17. package/locales/ar/providers.json +3 -0
  18. package/locales/bg-BG/models.json +6 -0
  19. package/locales/bg-BG/plugin.json +204 -144
  20. package/locales/bg-BG/providers.json +3 -0
  21. package/locales/de-DE/models.json +6 -0
  22. package/locales/de-DE/plugin.json +176 -116
  23. package/locales/de-DE/providers.json +3 -0
  24. package/locales/en-US/models.json +6 -0
  25. package/locales/en-US/plugin.json +192 -132
  26. package/locales/en-US/providers.json +3 -0
  27. package/locales/es-ES/models.json +6 -0
  28. package/locales/es-ES/plugin.json +203 -143
  29. package/locales/es-ES/providers.json +3 -0
  30. package/locales/fa-IR/models.json +6 -0
  31. package/locales/fa-IR/plugin.json +155 -95
  32. package/locales/fa-IR/providers.json +3 -0
  33. package/locales/fr-FR/models.json +6 -0
  34. package/locales/fr-FR/plugin.json +161 -101
  35. package/locales/fr-FR/providers.json +3 -0
  36. package/locales/it-IT/models.json +6 -0
  37. package/locales/it-IT/plugin.json +193 -133
  38. package/locales/it-IT/providers.json +3 -0
  39. package/locales/ja-JP/models.json +6 -0
  40. package/locales/ja-JP/plugin.json +195 -135
  41. package/locales/ja-JP/providers.json +3 -0
  42. package/locales/ko-KR/models.json +6 -0
  43. package/locales/ko-KR/plugin.json +163 -103
  44. package/locales/ko-KR/providers.json +3 -0
  45. package/locales/nl-NL/models.json +6 -0
  46. package/locales/nl-NL/plugin.json +211 -151
  47. package/locales/nl-NL/providers.json +3 -0
  48. package/locales/pl-PL/models.json +6 -0
  49. package/locales/pl-PL/plugin.json +171 -111
  50. package/locales/pl-PL/providers.json +3 -0
  51. package/locales/pt-BR/models.json +6 -0
  52. package/locales/pt-BR/plugin.json +180 -120
  53. package/locales/pt-BR/providers.json +3 -0
  54. package/locales/ru-RU/models.json +6 -0
  55. package/locales/ru-RU/plugin.json +191 -131
  56. package/locales/ru-RU/providers.json +3 -0
  57. package/locales/tr-TR/models.json +6 -0
  58. package/locales/tr-TR/plugin.json +187 -127
  59. package/locales/tr-TR/providers.json +3 -0
  60. package/locales/vi-VN/models.json +6 -0
  61. package/locales/vi-VN/plugin.json +152 -92
  62. package/locales/vi-VN/providers.json +3 -0
  63. package/locales/zh-CN/models.json +6 -0
  64. package/locales/zh-CN/plugin.json +60 -0
  65. package/locales/zh-CN/providers.json +3 -0
  66. package/locales/zh-TW/models.json +6 -0
  67. package/locales/zh-TW/plugin.json +157 -97
  68. package/locales/zh-TW/providers.json +3 -0
  69. package/package.json +2 -1
  70. package/packages/electron-client-ipc/src/events/index.ts +5 -2
  71. package/packages/electron-client-ipc/src/events/protocol.ts +29 -0
  72. package/packages/electron-client-ipc/src/types/index.ts +1 -0
  73. package/packages/electron-client-ipc/src/types/mcpInstall.ts +19 -0
  74. package/packages/types/src/plugins/mcp.ts +38 -1
  75. package/packages/types/src/plugins/protocol.ts +166 -0
  76. package/src/app/[variants]/(main)/chat/_layout/Desktop/index.tsx +4 -1
  77. package/src/app/[variants]/(main)/discover/(detail)/mcp/[slug]/features/Sidebar/ActionButton/index.tsx +1 -2
  78. package/src/components/KeyValueEditor/index.tsx +4 -2
  79. package/src/config/aiModels/aihubmix.ts +465 -30
  80. package/src/config/aiModels/anthropic.ts +27 -1
  81. package/src/config/aiModels/groq.ts +40 -4
  82. package/src/config/aiModels/qwen.ts +24 -2
  83. package/src/features/MCP/MCPInstallProgress/index.tsx +1 -1
  84. package/src/features/PluginDevModal/MCPManifestForm/index.tsx +30 -36
  85. package/src/features/PluginStore/McpList/List/Item.tsx +1 -1
  86. package/src/features/ProtocolUrlHandler/InstallPlugin/ConfigDisplay.tsx +211 -0
  87. package/src/features/ProtocolUrlHandler/InstallPlugin/CustomPluginInstallModal.tsx +228 -0
  88. package/src/features/ProtocolUrlHandler/InstallPlugin/OfficialPluginInstallModal/Detail.tsx +44 -0
  89. package/src/features/ProtocolUrlHandler/InstallPlugin/OfficialPluginInstallModal/index.tsx +105 -0
  90. package/src/features/ProtocolUrlHandler/InstallPlugin/index.tsx +55 -0
  91. package/src/features/ProtocolUrlHandler/InstallPlugin/types.ts +45 -0
  92. package/src/features/ProtocolUrlHandler/index.tsx +30 -0
  93. package/src/libs/model-runtime/anthropic/index.ts +15 -2
  94. package/src/libs/model-runtime/utils/modelParse.ts +2 -2
  95. package/src/libs/model-runtime/utils/streams/ollama.test.ts +97 -51
  96. package/src/libs/model-runtime/utils/streams/ollama.ts +4 -0
  97. package/src/locales/default/plugin.ts +60 -0
  98. package/src/store/tool/slices/mcpStore/action.ts +127 -1
  99. package/src/store/tool/slices/mcpStore/initialState.ts +8 -13
  100. package/src/store/tool/slices/mcpStore/selectors.ts +13 -0
@@ -0,0 +1,166 @@
1
+ /**
2
+ * 协议来源类型
3
+ */
4
+ export enum ProtocolSource {
5
+ /** 社区贡献 */
6
+ COMMUNITY = 'community',
7
+ /** 开发者自定义 */
8
+ DEVELOPER = 'developer',
9
+ /** GitHub 官方 */
10
+ GITHUB_OFFICIAL = 'github_official',
11
+ /** 官方LobeHub市场 */
12
+ OFFICIAL = 'official',
13
+ /** 第三方市场 */
14
+ THIRD_PARTY = 'third_party',
15
+ }
16
+
17
+ /**
18
+ * MCP Schema - stdio 配置类型
19
+ */
20
+ export interface McpStdioConfig {
21
+ args?: string[];
22
+ command: string;
23
+ env?: Record<string, string>;
24
+ type: 'stdio';
25
+ }
26
+
27
+ /**
28
+ * MCP Schema - http 配置类型
29
+ */
30
+ export interface McpHttpConfig {
31
+ headers?: Record<string, string>;
32
+ type: 'http';
33
+ url: string;
34
+ }
35
+
36
+ /**
37
+ * MCP Schema 配置类型
38
+ */
39
+ export type McpConfig = McpStdioConfig | McpHttpConfig;
40
+
41
+ /**
42
+ * MCP Schema 对象
43
+ * 符合 RFC 0001 定义
44
+ */
45
+ export interface McpSchema {
46
+ /** 插件作者 */
47
+ author: string;
48
+ /** 插件配置 */
49
+ config: McpConfig;
50
+ /** 插件描述 */
51
+ description: string;
52
+ /** 插件主页 */
53
+ homepage?: string;
54
+ /** 插件图标 */
55
+ icon?: string;
56
+ /** 插件唯一标识符,必须与URL中的id参数匹配 */
57
+ identifier: string;
58
+ /** 插件名称 */
59
+ name: string;
60
+ /** 插件版本 (semver) */
61
+ version: string;
62
+ }
63
+
64
+ /**
65
+ * RFC 0001 协议参数
66
+ * lobehub://plugin/install?id=xxx&schema=xxx&marketId=xxx&meta_*=xxx
67
+ */
68
+ export interface McpInstallProtocolParamsRFC {
69
+ /** 可选的 UI 显示元数据,以 meta_ 为前缀 */
70
+ [key: `meta_${string}`]: string | undefined;
71
+ /** 插件的唯一标识符 */
72
+ id: string;
73
+ /** 提供该插件的 Marketplace 的唯一标识符 */
74
+ marketId?: string;
75
+ /** Base64URL 编码的 MCP Schema 对象 */
76
+ schema: string;
77
+ /** 插件类型,对于 MCP 固定为 'mcp' */
78
+ type: 'mcp';
79
+ }
80
+
81
+ /**
82
+ * 协议URL解析结果
83
+ */
84
+ export interface ProtocolUrlParsed {
85
+ /** 操作类型 (如: 'install') */
86
+ action: 'install' | 'configure' | 'update';
87
+ /** 解析后的参数 */
88
+ params: {
89
+ id: string;
90
+ marketId?: string;
91
+ type: string;
92
+ };
93
+ /** MCP Schema 对象 */
94
+ schema: McpSchema;
95
+ /** 协议来源 */
96
+ source: ProtocolSource;
97
+ /** 插件类型 (如: 'mcp') */
98
+ type: 'mcp' | 'plugin';
99
+ /** URL类型 (如: 'plugin') */
100
+ urlType: string;
101
+ }
102
+
103
+ /**
104
+ * 安装确认弹窗信息
105
+ */
106
+ export interface InstallConfirmationInfo {
107
+ dependencies?: string[];
108
+ permissions?: {
109
+ filesystem?: boolean;
110
+ network?: boolean;
111
+ system?: boolean;
112
+ };
113
+ pluginInfo: {
114
+ author?: string;
115
+ description: string;
116
+ homepage?: string;
117
+ icon?: string;
118
+ identifier: string;
119
+ name: string;
120
+ version: string;
121
+ };
122
+ source: {
123
+ platform?: {
124
+ name: string;
125
+ url?: string;
126
+ };
127
+ type: ProtocolSource;
128
+ verified: boolean; // 是否为验证来源
129
+ };
130
+ }
131
+
132
+ /**
133
+ * 协议处理器接口
134
+ */
135
+ export interface ProtocolHandler {
136
+ /**
137
+ * 处理协议URL
138
+ */
139
+ handle(
140
+ parsed: ProtocolUrlParsed,
141
+ ): Promise<{ error?: string; success: boolean; targetWindow?: string }>;
142
+
143
+ /**
144
+ * 支持的操作
145
+ */
146
+ readonly supportedActions: string[];
147
+
148
+ /**
149
+ * 协议类型
150
+ */
151
+ readonly type: string;
152
+ }
153
+
154
+ /**
155
+ * 协议路由配置
156
+ */
157
+ export interface ProtocolRouteConfig {
158
+ /** 操作类型 */
159
+ action: string;
160
+ /** 目标路径(相对于窗口base路径) */
161
+ targetPath?: string;
162
+ /** 目标窗口 */
163
+ targetWindow: 'chat' | 'settings';
164
+ /** 协议类型 */
165
+ type: string;
166
+ }
@@ -1,7 +1,9 @@
1
1
  import { Suspense } from 'react';
2
2
  import { Flexbox } from 'react-layout-kit';
3
3
 
4
+ import { isDesktop } from '@/const/version';
4
5
  import InitClientDB from '@/features/InitClientDB';
6
+ import ProtocolUrlHandler from '@/features/ProtocolUrlHandler';
5
7
 
6
8
  import { LayoutProps } from '../type';
7
9
  import RegisterHotkeys from './RegisterHotkeys';
@@ -20,13 +22,14 @@ const Layout = ({ children, session }: LayoutProps) => {
20
22
  <SessionPanel>{session}</SessionPanel>
21
23
  <Workspace>{children}</Workspace>
22
24
  </Flexbox>
23
- <InitClientDB bottom={60} />
25
+ {!isDesktop && <InitClientDB bottom={60} />}
24
26
  {/* ↓ cloud slot ↓ */}
25
27
 
26
28
  {/* ↑ cloud slot ↑ */}
27
29
  <Suspense>
28
30
  <RegisterHotkeys />
29
31
  </Suspense>
32
+ {isDesktop && <ProtocolUrlHandler />}
30
33
  </>
31
34
  );
32
35
  };
@@ -22,6 +22,7 @@ const useStyles = createStyles(({ css }) => ({
22
22
  }));
23
23
 
24
24
  const ActionButton = memo(() => {
25
+ const { t } = useTranslation(['discover', 'plugin']);
25
26
  const { identifier } = useDetailContext();
26
27
  const { styles } = useStyles();
27
28
  const [isLoading, setIsLoading] = useState(false);
@@ -32,8 +33,6 @@ const ActionButton = memo(() => {
32
33
  s.uninstallMCPPlugin,
33
34
  ]);
34
35
 
35
- const { t } = useTranslation(['discover', 'plugin']);
36
-
37
36
  const installPlugin = async () => {
38
37
  if (!identifier) return;
39
38
  setIsLoading(true);
@@ -3,7 +3,7 @@ import { Button } from 'antd';
3
3
  import { createStyles } from 'antd-style';
4
4
  import fastDeepEqual from 'fast-deep-equal';
5
5
  import { LucidePlus, LucideTrash } from 'lucide-react';
6
- import { memo, useEffect, useRef, useState } from 'react';
6
+ import { CSSProperties, memo, useEffect, useRef, useState } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
8
  import { Flexbox } from 'react-layout-kit';
9
9
  import { v4 as uuidv4 } from 'uuid';
@@ -44,6 +44,7 @@ export interface KeyValueEditorProps {
44
44
  duplicateKeyErrorText?: string;
45
45
  keyPlaceholder?: string;
46
46
  onChange?: (value: Record<string, string>) => void;
47
+ style?: CSSProperties;
47
48
  value?: Record<string, string>;
48
49
  valuePlaceholder?: string;
49
50
  }
@@ -57,6 +58,7 @@ const KeyValueEditor = memo<KeyValueEditorProps>(
57
58
  addButtonText,
58
59
  duplicateKeyErrorText,
59
60
  deleteTooltip,
61
+ style,
60
62
  }) => {
61
63
  const { styles } = useStyles();
62
64
  const { t } = useTranslation('components');
@@ -125,7 +127,7 @@ const KeyValueEditor = memo<KeyValueEditorProps>(
125
127
  const duplicateKeys = getDuplicateKeys(items);
126
128
 
127
129
  return (
128
- <div className={styles.container}>
130
+ <div className={styles.container} style={style}>
129
131
  <Flexbox className={styles.title} gap={8} horizontal>
130
132
  <Flexbox flex={1}>{keyPlaceholder || t('KeyValueEditor.keyPlaceholder')}</Flexbox>
131
133
  <Flexbox flex={2}>{valuePlaceholder || t('KeyValueEditor.valuePlaceholder')}</Flexbox>