@lobehub/chat 1.81.8 → 1.82.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.
- package/CHANGELOG.md +50 -0
- package/changelog/v1.json +18 -0
- package/locales/ar/plugin.json +33 -2
- package/locales/bg-BG/plugin.json +33 -2
- package/locales/de-DE/plugin.json +33 -2
- package/locales/en-US/plugin.json +33 -2
- package/locales/es-ES/plugin.json +33 -2
- package/locales/fa-IR/plugin.json +33 -2
- package/locales/fr-FR/plugin.json +33 -2
- package/locales/it-IT/plugin.json +33 -2
- package/locales/ja-JP/plugin.json +33 -2
- package/locales/ko-KR/plugin.json +33 -2
- package/locales/nl-NL/plugin.json +33 -2
- package/locales/pl-PL/plugin.json +33 -2
- package/locales/pt-BR/plugin.json +33 -2
- package/locales/ru-RU/plugin.json +33 -2
- package/locales/tr-TR/plugin.json +33 -2
- package/locales/vi-VN/plugin.json +33 -2
- package/locales/zh-CN/plugin.json +33 -2
- package/locales/zh-TW/plugin.json +33 -2
- package/package.json +1 -1
- package/packages/electron-client-ipc/src/events/localFile.ts +8 -2
- package/packages/electron-client-ipc/src/events/system.ts +3 -0
- package/packages/electron-client-ipc/src/types/index.ts +1 -0
- package/packages/electron-client-ipc/src/types/localFile.ts +46 -0
- package/packages/electron-client-ipc/src/types/system.ts +24 -0
- package/packages/file-loaders/src/blackList.ts +9 -0
- package/packages/file-loaders/src/index.ts +1 -0
- package/packages/file-loaders/src/loaders/pdf/index.test.ts +1 -0
- package/packages/file-loaders/src/loaders/pdf/index.ts +1 -7
- package/src/components/FileIcon/index.tsx +7 -3
- package/src/components/ManifestPreviewer/index.tsx +4 -1
- package/src/features/ChatInput/ActionBar/Tools/Dropdown.tsx +2 -1
- package/src/features/Conversation/Extras/Usage/index.tsx +7 -1
- package/src/features/Conversation/Messages/Assistant/Tool/Render/CustomRender.tsx +1 -1
- package/src/features/PluginAvatar/index.tsx +2 -1
- package/src/features/PluginDevModal/MCPManifestForm.tsx +164 -0
- package/src/features/PluginDevModal/PluginPreview.tsx +4 -3
- package/src/features/PluginDevModal/index.tsx +43 -34
- package/src/features/PluginStore/AddPluginButton.tsx +3 -1
- package/src/features/PluginStore/PluginItem/Action.tsx +5 -2
- package/src/features/PluginStore/PluginItem/PluginAvatar.tsx +25 -0
- package/src/features/PluginStore/PluginItem/index.tsx +4 -3
- package/src/features/PluginTag/index.tsx +8 -2
- package/src/{server/modules/MCPClient → libs/mcp}/__tests__/index.test.ts +2 -2
- package/src/{server/modules/MCPClient/index.ts → libs/mcp/client.ts} +29 -33
- package/src/libs/mcp/index.ts +2 -0
- package/src/libs/mcp/types.ts +27 -0
- package/src/locales/default/plugin.ts +34 -3
- package/src/server/routers/tools/index.ts +2 -0
- package/src/server/routers/tools/mcp.ts +79 -0
- package/src/server/services/mcp/index.ts +157 -0
- package/src/services/electron/localFileService.ts +19 -0
- package/src/services/electron/system.ts +21 -0
- package/src/services/mcp.ts +25 -0
- package/src/store/chat/slices/builtinTool/actions/search.ts +0 -3
- package/src/store/chat/slices/plugin/action.ts +46 -2
- package/src/tools/local-files/Render/ListFiles/index.tsx +24 -17
- package/src/tools/local-files/Render/ReadLocalFile/ReadFileView.tsx +28 -28
- package/src/tools/local-files/components/FileItem.tsx +9 -11
- package/src/tools/local-files/index.ts +60 -2
- package/src/tools/local-files/systemRole.ts +53 -13
- package/src/tools/local-files/type.ts +19 -1
- package/src/tools/web-browsing/systemRole.ts +40 -38
- package/src/types/tool/plugin.ts +9 -0
- /package/src/{server/modules/MCPClient → libs/mcp}/__tests__/__snapshots__/index.test.ts.snap +0 -0
@@ -34,9 +34,40 @@
|
|
34
34
|
"desc": "Identificador único do plugin",
|
35
35
|
"label": "Identificador"
|
36
36
|
},
|
37
|
+
"mcp": {
|
38
|
+
"args": {
|
39
|
+
"desc": "Lista de parâmetros a serem passados para o comando STDIO",
|
40
|
+
"label": "Parâmetros do comando",
|
41
|
+
"placeholder": "Por exemplo: --port 8080 --debug",
|
42
|
+
"tooltip": "Pressione Enter após inserir os parâmetros ou use vírgula/espaço para separar"
|
43
|
+
},
|
44
|
+
"command": {
|
45
|
+
"desc": "Arquivo executável ou script usado para iniciar o plugin MCP STDIO",
|
46
|
+
"label": "Comando",
|
47
|
+
"placeholder": "Por exemplo: python main.py ou /caminho/para/executável"
|
48
|
+
},
|
49
|
+
"endpoint": {
|
50
|
+
"desc": "Insira o endereço do seu Servidor HTTP Streamable MCP",
|
51
|
+
"label": "URL do Endpoint MCP"
|
52
|
+
},
|
53
|
+
"identifier": {
|
54
|
+
"desc": "Dê um nome ao seu plugin MCP, deve usar caracteres em inglês",
|
55
|
+
"invalid": "Somente caracteres em inglês, números, - e _ são permitidos",
|
56
|
+
"label": "Nome do plugin MCP",
|
57
|
+
"placeholder": "Por exemplo: meu-plugin-mcp"
|
58
|
+
},
|
59
|
+
"type": {
|
60
|
+
"desc": "Escolha o método de comunicação do plugin MCP, a versão web suporta apenas HTTP Streamable",
|
61
|
+
"label": "Tipo de plugin MCP"
|
62
|
+
},
|
63
|
+
"url": {
|
64
|
+
"desc": "Insira o endereço do Endpoint do seu plugin HTTP MCP",
|
65
|
+
"label": "URL do Endpoint HTTP"
|
66
|
+
}
|
67
|
+
},
|
37
68
|
"mode": {
|
38
|
-
"
|
39
|
-
"
|
69
|
+
"mcp": "Plugin MCP",
|
70
|
+
"mcpExp": "Experimental",
|
40
71
|
"url": "Link Online"
|
41
72
|
},
|
42
73
|
"name": {
|
@@ -34,9 +34,40 @@
|
|
34
34
|
"desc": "Уникальный идентификатор плагина",
|
35
35
|
"label": "Идентификатор"
|
36
36
|
},
|
37
|
+
"mcp": {
|
38
|
+
"args": {
|
39
|
+
"desc": "Список параметров, передаваемых в команду STDIO",
|
40
|
+
"label": "Параметры команды",
|
41
|
+
"placeholder": "Например: --port 8080 --debug",
|
42
|
+
"tooltip": "Нажмите Enter после ввода параметров или используйте запятую/пробел для разделения"
|
43
|
+
},
|
44
|
+
"command": {
|
45
|
+
"desc": "Исполняемый файл или скрипт для запуска MCP STDIO плагина",
|
46
|
+
"label": "Команда",
|
47
|
+
"placeholder": "Например: python main.py или /path/to/executable"
|
48
|
+
},
|
49
|
+
"endpoint": {
|
50
|
+
"desc": "Введите адрес вашего MCP Streamable HTTP сервера",
|
51
|
+
"label": "MCP Endpoint URL"
|
52
|
+
},
|
53
|
+
"identifier": {
|
54
|
+
"desc": "Укажите имя для вашего MCP плагина, необходимо использовать английские символы",
|
55
|
+
"invalid": "Можно вводить только английские буквы, цифры, символы - и _",
|
56
|
+
"label": "Имя MCP плагина",
|
57
|
+
"placeholder": "Например: my-mcp-plugin"
|
58
|
+
},
|
59
|
+
"type": {
|
60
|
+
"desc": "Выберите способ связи для MCP плагина, веб-версия поддерживает только Streamable HTTP",
|
61
|
+
"label": "Тип MCP плагина"
|
62
|
+
},
|
63
|
+
"url": {
|
64
|
+
"desc": "Введите адрес Endpoint вашего MCP HTTP плагина",
|
65
|
+
"label": "HTTP Endpoint URL"
|
66
|
+
}
|
67
|
+
},
|
37
68
|
"mode": {
|
38
|
-
"
|
39
|
-
"
|
69
|
+
"mcp": "MCP плагин",
|
70
|
+
"mcpExp": "Экспериментальный",
|
40
71
|
"url": "Ссылка онлайн"
|
41
72
|
},
|
42
73
|
"name": {
|
@@ -34,9 +34,40 @@
|
|
34
34
|
"desc": "Eklenti için benzersiz tanımlayıcı",
|
35
35
|
"label": "Tanımlayıcı"
|
36
36
|
},
|
37
|
+
"mcp": {
|
38
|
+
"args": {
|
39
|
+
"desc": "STDIO komutuna iletilen parametreler listesi",
|
40
|
+
"label": "Komut Parametreleri",
|
41
|
+
"placeholder": "Örneğin: --port 8080 --debug",
|
42
|
+
"tooltip": "Parametreleri girdikten sonra enter tuşuna basın veya virgül/boşluk ile ayırın"
|
43
|
+
},
|
44
|
+
"command": {
|
45
|
+
"desc": "MCP STDIO eklentisini başlatmak için kullanılacak yürütülebilir dosya veya betik",
|
46
|
+
"label": "Komut",
|
47
|
+
"placeholder": "Örneğin: python main.py veya /path/to/executable"
|
48
|
+
},
|
49
|
+
"endpoint": {
|
50
|
+
"desc": "MCP Streamable HTTP Sunucunuzun adresini girin",
|
51
|
+
"label": "MCP Endpoint URL"
|
52
|
+
},
|
53
|
+
"identifier": {
|
54
|
+
"desc": "MCP eklentinize bir ad verin, İngilizce karakterler kullanmalısınız",
|
55
|
+
"invalid": "Sadece İngilizce karakterler, rakamlar, - ve _ bu iki sembolü girebilirsiniz",
|
56
|
+
"label": "MCP Eklenti Adı",
|
57
|
+
"placeholder": "Örneğin: my-mcp-plugin"
|
58
|
+
},
|
59
|
+
"type": {
|
60
|
+
"desc": "MCP eklentisinin iletişim yöntemini seçin, web sürümü yalnızca Streamable HTTP'yi destekler",
|
61
|
+
"label": "MCP Eklenti Türü"
|
62
|
+
},
|
63
|
+
"url": {
|
64
|
+
"desc": "MCP HTTP eklentinizin Endpoint adresini girin",
|
65
|
+
"label": "HTTP Endpoint URL"
|
66
|
+
}
|
67
|
+
},
|
37
68
|
"mode": {
|
38
|
-
"
|
39
|
-
"
|
69
|
+
"mcp": "MCP Eklentisi",
|
70
|
+
"mcpExp": "Deneysel",
|
40
71
|
"url": "Çevrimiçi Bağlantı"
|
41
72
|
},
|
42
73
|
"name": {
|
@@ -35,8 +35,8 @@
|
|
35
35
|
"label": "Định danh"
|
36
36
|
},
|
37
37
|
"mode": {
|
38
|
-
"
|
39
|
-
"
|
38
|
+
"mcp": "MCP Plugin",
|
39
|
+
"mcpExp": "Thí nghiệm",
|
40
40
|
"url": "Liên kết trực tuyến"
|
41
41
|
},
|
42
42
|
"name": {
|
@@ -45,6 +45,37 @@
|
|
45
45
|
"placeholder": "Tìm kiếm công cụ tìm kiếm"
|
46
46
|
}
|
47
47
|
},
|
48
|
+
"mcp": {
|
49
|
+
"args": {
|
50
|
+
"desc": "Danh sách các tham số được truyền cho lệnh STDIO",
|
51
|
+
"label": "Tham số lệnh",
|
52
|
+
"placeholder": "Ví dụ: --port 8080 --debug",
|
53
|
+
"tooltip": "Nhấn Enter sau khi nhập tham số hoặc sử dụng dấu phẩy/khoảng trắng để phân tách"
|
54
|
+
},
|
55
|
+
"command": {
|
56
|
+
"desc": "Tệp thực thi hoặc kịch bản để khởi động plugin MCP STDIO",
|
57
|
+
"label": "Lệnh",
|
58
|
+
"placeholder": "Ví dụ: python main.py hoặc /path/to/executable"
|
59
|
+
},
|
60
|
+
"endpoint": {
|
61
|
+
"desc": "Nhập địa chỉ của máy chủ HTTP Streamable MCP của bạn",
|
62
|
+
"label": "URL Điểm cuối MCP"
|
63
|
+
},
|
64
|
+
"identifier": {
|
65
|
+
"desc": "Chỉ định một tên cho plugin MCP của bạn, cần sử dụng ký tự tiếng Anh",
|
66
|
+
"invalid": "Chỉ có thể nhập ký tự tiếng Anh, số, và hai ký hiệu - và _",
|
67
|
+
"label": "Tên plugin MCP",
|
68
|
+
"placeholder": "Ví dụ: my-mcp-plugin"
|
69
|
+
},
|
70
|
+
"type": {
|
71
|
+
"desc": "Chọn phương thức giao tiếp của plugin MCP, phiên bản web chỉ hỗ trợ Streamable HTTP",
|
72
|
+
"label": "Loại plugin MCP"
|
73
|
+
},
|
74
|
+
"url": {
|
75
|
+
"desc": "Nhập địa chỉ Điểm cuối HTTP của plugin MCP của bạn",
|
76
|
+
"label": "URL Điểm cuối HTTP"
|
77
|
+
}
|
78
|
+
},
|
48
79
|
"meta": {
|
49
80
|
"author": {
|
50
81
|
"desc": "Tác giả của plugin",
|
@@ -35,8 +35,8 @@
|
|
35
35
|
"label": "标识符"
|
36
36
|
},
|
37
37
|
"mode": {
|
38
|
-
"
|
39
|
-
"
|
38
|
+
"mcp": "MCP 插件",
|
39
|
+
"mcpExp": "实验性",
|
40
40
|
"url": "在线链接"
|
41
41
|
},
|
42
42
|
"name": {
|
@@ -45,6 +45,37 @@
|
|
45
45
|
"placeholder": "搜索引擎"
|
46
46
|
}
|
47
47
|
},
|
48
|
+
"mcp": {
|
49
|
+
"args": {
|
50
|
+
"desc": "传递给 STDIO 命令的参数列表",
|
51
|
+
"label": "命令参数",
|
52
|
+
"placeholder": "例如:--port 8080 --debug",
|
53
|
+
"tooltip": "输入参数后按回车或使用逗号/空格分隔"
|
54
|
+
},
|
55
|
+
"command": {
|
56
|
+
"desc": "用于启动 MCP STDIO 插件的可执行文件或脚本",
|
57
|
+
"label": "命令",
|
58
|
+
"placeholder": "例如:python main.py 或 /path/to/executable"
|
59
|
+
},
|
60
|
+
"endpoint": {
|
61
|
+
"desc": "输入你的 MCP Streamable HTTP Server 的地址",
|
62
|
+
"label": "MCP Endpoint URL"
|
63
|
+
},
|
64
|
+
"identifier": {
|
65
|
+
"desc": "为你的 MCP 插件指定一个名称,需要使用英文字符",
|
66
|
+
"invalid": "只能输入英文字符、数字 、- 和_ 这两个符号",
|
67
|
+
"label": "MCP 插件名称",
|
68
|
+
"placeholder": "例如:my-mcp-plugin"
|
69
|
+
},
|
70
|
+
"type": {
|
71
|
+
"desc": "选择 MCP 插件的通信方式,网页版只支持 Streamable HTTP",
|
72
|
+
"label": "MCP 插件类型"
|
73
|
+
},
|
74
|
+
"url": {
|
75
|
+
"desc": "输入你的 MCP HTTP 插件的 Endpoint 地址",
|
76
|
+
"label": "HTTP Endpoint URL"
|
77
|
+
}
|
78
|
+
},
|
48
79
|
"meta": {
|
49
80
|
"author": {
|
50
81
|
"desc": "插件的作者",
|
@@ -34,9 +34,40 @@
|
|
34
34
|
"desc": "外掛的唯一識別碼",
|
35
35
|
"label": "識別碼"
|
36
36
|
},
|
37
|
+
"mcp": {
|
38
|
+
"args": {
|
39
|
+
"desc": "傳遞給 STDIO 命令的參數列表",
|
40
|
+
"label": "命令參數",
|
41
|
+
"placeholder": "例如:--port 8080 --debug",
|
42
|
+
"tooltip": "輸入參數後按回車或使用逗號/空格分隔"
|
43
|
+
},
|
44
|
+
"command": {
|
45
|
+
"desc": "用於啟動 MCP STDIO 插件的可執行文件或腳本",
|
46
|
+
"label": "命令",
|
47
|
+
"placeholder": "例如:python main.py 或 /path/to/executable"
|
48
|
+
},
|
49
|
+
"endpoint": {
|
50
|
+
"desc": "輸入你的 MCP Streamable HTTP Server 的地址",
|
51
|
+
"label": "MCP Endpoint URL"
|
52
|
+
},
|
53
|
+
"identifier": {
|
54
|
+
"desc": "為你的 MCP 插件指定一個名稱,需要使用英文字符",
|
55
|
+
"invalid": "只能輸入英文字符、數字、- 和_ 這兩個符號",
|
56
|
+
"label": "MCP 插件名稱",
|
57
|
+
"placeholder": "例如:my-mcp-plugin"
|
58
|
+
},
|
59
|
+
"type": {
|
60
|
+
"desc": "選擇 MCP 插件的通信方式,網頁版只支持 Streamable HTTP",
|
61
|
+
"label": "MCP 插件類型"
|
62
|
+
},
|
63
|
+
"url": {
|
64
|
+
"desc": "輸入你的 MCP HTTP 插件的 Endpoint 地址",
|
65
|
+
"label": "HTTP Endpoint URL"
|
66
|
+
}
|
67
|
+
},
|
37
68
|
"mode": {
|
38
|
-
"
|
39
|
-
"
|
69
|
+
"mcp": "MCP 插件",
|
70
|
+
"mcpExp": "實驗性",
|
40
71
|
"url": "線上連結"
|
41
72
|
},
|
42
73
|
"name": {
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.82.0",
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot 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",
|
@@ -1,22 +1,28 @@
|
|
1
1
|
import {
|
2
2
|
ListLocalFileParams,
|
3
3
|
LocalFileItem,
|
4
|
+
LocalMoveFilesResultItem,
|
4
5
|
LocalReadFileParams,
|
5
6
|
LocalReadFileResult,
|
6
7
|
LocalReadFilesParams,
|
7
8
|
LocalSearchFilesParams,
|
9
|
+
MoveLocalFilesParams,
|
8
10
|
OpenLocalFileParams,
|
9
11
|
OpenLocalFolderParams,
|
12
|
+
RenameLocalFileParams,
|
13
|
+
RenameLocalFileResult,
|
10
14
|
} from '../types';
|
11
15
|
|
12
16
|
export interface LocalFilesDispatchEvents {
|
13
17
|
// Local Files API Events
|
14
18
|
listLocalFiles: (params: ListLocalFileParams) => LocalFileItem[];
|
15
|
-
|
19
|
+
moveLocalFiles: (params: MoveLocalFilesParams) => LocalMoveFilesResultItem[];
|
20
|
+
|
16
21
|
openLocalFile: (params: OpenLocalFileParams) => void;
|
17
22
|
openLocalFolder: (params: OpenLocalFolderParams) => void;
|
18
23
|
readLocalFile: (params: LocalReadFileParams) => LocalReadFileResult;
|
19
|
-
|
20
24
|
readLocalFiles: (params: LocalReadFilesParams) => LocalReadFileResult[];
|
25
|
+
|
26
|
+
renameLocalFile: (params: RenameLocalFileParams) => RenameLocalFileResult;
|
21
27
|
searchLocalFiles: (params: LocalSearchFilesParams) => LocalFileItem[];
|
22
28
|
}
|
@@ -19,7 +19,35 @@ export interface ListLocalFileParams {
|
|
19
19
|
path: string;
|
20
20
|
}
|
21
21
|
|
22
|
+
export interface MoveLocalFileParams {
|
23
|
+
newPath: string;
|
24
|
+
oldPath: string;
|
25
|
+
}
|
26
|
+
|
27
|
+
export interface MoveLocalFilesParams {
|
28
|
+
items: MoveLocalFileParams[];
|
29
|
+
}
|
30
|
+
|
31
|
+
export interface LocalMoveFilesResultItem {
|
32
|
+
error?: string; // Error message if this specific item failed
|
33
|
+
newPath?: string; // The final path after moving/renaming, if successful
|
34
|
+
sourcePath: string; // The original path of the item being moved/renamed
|
35
|
+
success: boolean; // Whether the operation for this specific item was successful
|
36
|
+
}
|
37
|
+
|
38
|
+
export interface RenameLocalFileParams {
|
39
|
+
newName: string;
|
40
|
+
path: string;
|
41
|
+
}
|
42
|
+
|
43
|
+
export interface RenameLocalFileResult {
|
44
|
+
error?: any;
|
45
|
+
newPath: string;
|
46
|
+
success: boolean;
|
47
|
+
}
|
48
|
+
|
22
49
|
export interface LocalReadFileParams {
|
50
|
+
loc?: [number, number];
|
23
51
|
path: string;
|
24
52
|
}
|
25
53
|
|
@@ -28,13 +56,31 @@ export interface LocalReadFilesParams {
|
|
28
56
|
}
|
29
57
|
|
30
58
|
export interface LocalReadFileResult {
|
59
|
+
/**
|
60
|
+
* Character count of the content within the specified `loc` range.
|
61
|
+
*/
|
31
62
|
charCount: number;
|
63
|
+
/**
|
64
|
+
* Content of the file within the specified `loc` range.
|
65
|
+
*/
|
32
66
|
content: string;
|
33
67
|
createdTime: Date;
|
34
68
|
fileType: string;
|
35
69
|
filename: string;
|
70
|
+
/**
|
71
|
+
* Line count of the content within the specified `loc` range.
|
72
|
+
*/
|
36
73
|
lineCount: number;
|
74
|
+
loc: [number, number];
|
37
75
|
modifiedTime: Date;
|
76
|
+
/**
|
77
|
+
* Total character count of the entire file.
|
78
|
+
*/
|
79
|
+
totalCharCount: number;
|
80
|
+
/**
|
81
|
+
* Total line count of the entire file.
|
82
|
+
*/
|
83
|
+
totalLineCount: number;
|
38
84
|
}
|
39
85
|
|
40
86
|
export interface LocalSearchFilesParams {
|
@@ -0,0 +1,24 @@
|
|
1
|
+
export interface ElectronAppState {
|
2
|
+
arch?: string; // e.g., 'x64', 'arm64'
|
3
|
+
isLinux?: boolean;
|
4
|
+
isMac?: boolean;
|
5
|
+
isWindows?: boolean;
|
6
|
+
platform?: 'darwin' | 'win32' | 'linux'; // , etc.
|
7
|
+
userPath?: UserPathData;
|
8
|
+
}
|
9
|
+
|
10
|
+
/**
|
11
|
+
* Defines the structure for user-specific paths obtained from Electron.
|
12
|
+
*/
|
13
|
+
export interface UserPathData {
|
14
|
+
desktop: string;
|
15
|
+
documents: string;
|
16
|
+
downloads?: string;
|
17
|
+
// App data directory
|
18
|
+
home: string;
|
19
|
+
// Optional as not all OS might have it easily accessible or standard
|
20
|
+
music?: string;
|
21
|
+
pictures?: string;
|
22
|
+
userData: string;
|
23
|
+
videos?: string; // User's home directory
|
24
|
+
}
|
@@ -42,6 +42,7 @@ describe('PdfLoader', () => {
|
|
42
42
|
|
43
43
|
it('should attach document metadata correctly', async () => {
|
44
44
|
// 首先加载页面以初始化 pdfInstance,尽管此方法不直接使用页面
|
45
|
+
await loader.loadPages(testFile);
|
45
46
|
const metadata = await loader.attachDocumentMetadata!(testFile);
|
46
47
|
|
47
48
|
expect(metadata).toMatchSnapshot();
|
@@ -11,8 +11,6 @@ export class PdfLoader implements FileLoaderInterface {
|
|
11
11
|
private pdfInstance: PDFDocumentProxy | null = null;
|
12
12
|
|
13
13
|
private async getPDFFile(filePath: string) {
|
14
|
-
if (!!this.pdfInstance) return this.pdfInstance;
|
15
|
-
|
16
14
|
const dataBuffer = await readFile(filePath);
|
17
15
|
|
18
16
|
const loadingTask = pdfjsLib.getDocument({
|
@@ -22,11 +20,7 @@ export class PdfLoader implements FileLoaderInterface {
|
|
22
20
|
worker: undefined, // Attempt to use system fonts
|
23
21
|
});
|
24
22
|
|
25
|
-
|
26
|
-
|
27
|
-
this.pdfInstance = pdf;
|
28
|
-
|
29
|
-
return pdf;
|
23
|
+
return await loadingTask.promise;
|
30
24
|
}
|
31
25
|
|
32
26
|
async loadPages(filePath: string): Promise<DocumentPage[]> {
|
@@ -1,16 +1,20 @@
|
|
1
1
|
import { FileTypeIcon, MaterialFileTypeIcon } from '@lobehub/ui';
|
2
|
-
import { memo } from 'react';
|
2
|
+
import React, { memo } from 'react';
|
3
3
|
|
4
4
|
import { mimeTypeMap } from './config';
|
5
5
|
|
6
6
|
interface FileListProps {
|
7
7
|
fileName: string;
|
8
|
-
fileType
|
8
|
+
fileType?: string;
|
9
|
+
isDirectory?: boolean;
|
9
10
|
size?: number;
|
10
11
|
variant?: 'pure' | 'file' | 'folder';
|
11
12
|
}
|
12
13
|
|
13
|
-
const FileIcon = memo<FileListProps>(({ fileName, size, variant = 'file' }) => {
|
14
|
+
const FileIcon = memo<FileListProps>(({ fileName, size, variant = 'file', isDirectory }) => {
|
15
|
+
if (isDirectory)
|
16
|
+
return <FileTypeIcon color={'gold'} size={size} type={'folder'} variant={'color'} />;
|
17
|
+
|
14
18
|
if (Object.keys(mimeTypeMap).some((key) => fileName?.toLowerCase().endsWith(`.${key}`))) {
|
15
19
|
const ext = fileName.split('.').pop()?.toLowerCase() as string;
|
16
20
|
|
@@ -13,7 +13,10 @@ const ManifestPreviewer = memo<PluginManifestPreviewerProps>(
|
|
13
13
|
<Popover
|
14
14
|
arrow={false}
|
15
15
|
content={
|
16
|
-
<Highlighter
|
16
|
+
<Highlighter
|
17
|
+
language={'json'}
|
18
|
+
style={{ maxHeight: 600, maxWidth: 400, overflow: 'scroll' }}
|
19
|
+
>
|
17
20
|
{JSON.stringify(manifest, null, 2)}
|
18
21
|
</Highlighter>
|
19
22
|
}
|
@@ -9,6 +9,7 @@ import { useTranslation } from 'react-i18next';
|
|
9
9
|
import { Flexbox } from 'react-layout-kit';
|
10
10
|
|
11
11
|
import PluginStore from '@/features/PluginStore';
|
12
|
+
import PluginAvatar from '@/features/PluginStore/PluginItem/PluginAvatar';
|
12
13
|
import { useCheckPluginsIsInstalled } from '@/hooks/useCheckPluginsIsInstalled';
|
13
14
|
import { useFetchInstalledPlugins } from '@/hooks/useFetchInstalledPlugins';
|
14
15
|
import { useWorkspaceModal } from '@/hooks/useWorkspaceModal';
|
@@ -67,7 +68,7 @@ const DropdownMenu = memo<PropsWithChildren>(({ children }) => {
|
|
67
68
|
children: [
|
68
69
|
...list.map((item) => ({
|
69
70
|
icon: item.meta?.avatar ? (
|
70
|
-
<
|
71
|
+
<PluginAvatar avatar={pluginHelpers.getPluginAvatar(item.meta)} size={24} />
|
71
72
|
) : (
|
72
73
|
<Icon icon={ToyBrick} size={{ fontSize: 16 }} style={{ padding: 4 }} />
|
73
74
|
),
|
@@ -24,7 +24,13 @@ const Usage = memo<UsageProps>(({ model, metadata, provider }) => {
|
|
24
24
|
const { styles } = useStyles();
|
25
25
|
|
26
26
|
return (
|
27
|
-
<Flexbox
|
27
|
+
<Flexbox
|
28
|
+
align={'center'}
|
29
|
+
className={styles.container}
|
30
|
+
gap={12}
|
31
|
+
horizontal
|
32
|
+
justify={'space-between'}
|
33
|
+
>
|
28
34
|
<Center gap={4} horizontal style={{ fontSize: 12 }}>
|
29
35
|
<ModelIcon model={model as string} type={'mono'} />
|
30
36
|
{model}
|
@@ -75,7 +75,7 @@ const CustomRender = memo<CustomRenderProps>(
|
|
75
75
|
useEffect(() => {
|
76
76
|
if (!plugin?.type || loading) return;
|
77
77
|
|
78
|
-
setShowPluginRender(plugin?.type
|
78
|
+
setShowPluginRender(!['default', 'mcp'].includes(plugin?.type));
|
79
79
|
}, [plugin?.type, loading]);
|
80
80
|
|
81
81
|
if (loading) return <Arguments arguments={requestArgs} shine />;
|
@@ -1,9 +1,10 @@
|
|
1
|
-
import {
|
1
|
+
import { Icon } from '@lobehub/ui';
|
2
2
|
import isEqual from 'fast-deep-equal';
|
3
3
|
import { LucideToyBrick } from 'lucide-react';
|
4
4
|
import { memo } from 'react';
|
5
5
|
import { useTranslation } from 'react-i18next';
|
6
6
|
|
7
|
+
import Avatar from '@/features/PluginStore/PluginItem/PluginAvatar';
|
7
8
|
import { pluginHelpers, useToolStore } from '@/store/tool';
|
8
9
|
import { toolSelectors } from '@/store/tool/selectors';
|
9
10
|
|