@lobehub/lobehub 2.0.0-next.62 → 2.0.0-next.63
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/changelog/v1.json +9 -0
- package/locales/ar/plugin.json +2 -0
- package/locales/bg-BG/plugin.json +2 -0
- package/locales/de-DE/plugin.json +2 -0
- package/locales/en-US/plugin.json +8 -1
- package/locales/es-ES/plugin.json +2 -0
- package/locales/fa-IR/plugin.json +2 -0
- package/locales/fr-FR/plugin.json +2 -0
- package/locales/it-IT/plugin.json +2 -0
- package/locales/ja-JP/plugin.json +2 -0
- package/locales/ko-KR/plugin.json +2 -0
- package/locales/nl-NL/plugin.json +2 -0
- package/locales/pl-PL/plugin.json +2 -0
- package/locales/pt-BR/plugin.json +2 -0
- package/locales/ru-RU/plugin.json +2 -0
- package/locales/tr-TR/plugin.json +2 -0
- package/locales/vi-VN/plugin.json +2 -0
- package/locales/zh-CN/plugin.json +8 -1
- package/locales/zh-TW/plugin.json +2 -0
- package/package.json +1 -1
- package/src/components/FileIcon/index.tsx +0 -2
- package/src/features/Conversation/Messages/Assistant/MessageContent.tsx +0 -18
- package/src/features/Conversation/Messages/Group/Tool/Inspector/index.tsx +26 -5
- package/src/features/Conversation/Messages/Group/Tool/index.tsx +1 -1
- package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Inspector/ToolTitle.tsx +1 -7
- package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Inspector/index.tsx +2 -15
- package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Render/CustomRender.tsx +1 -1
- package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Render/PluginSettings.tsx +2 -2
- package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Render/index.tsx +2 -31
- package/src/features/Conversation/Messages/Tool/ToolItem.tsx +51 -0
- package/src/features/Conversation/Messages/Tool/index.tsx +58 -0
- package/src/features/Conversation/Messages/index.tsx +5 -0
- package/src/features/ShareModal/ShareJSON/index.tsx +2 -2
- package/src/locales/default/plugin.ts +8 -0
- package/src/store/chat/slices/message/action.test.ts +8 -4
- package/src/store/chat/slices/message/actions/optimisticUpdate.ts +12 -0
- package/src/store/chat/slices/message/actions/publicApi.ts +19 -17
- package/src/tools/local-system/index.ts +27 -27
- package/src/tools/local-system/systemRole.ts +7 -7
- package/src/features/Conversation/Messages/Assistant/Tool/Render/LoadingPlaceholder/index.tsx +0 -29
- package/src/features/Conversation/Messages/Assistant/Tool/index.tsx +0 -76
- /package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Inspector/BuiltinPluginTitle.tsx +0 -0
- /package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Inspector/Debug.tsx +0 -0
- /package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Inspector/PluginResult.tsx +0 -0
- /package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Inspector/PluginState.tsx +0 -0
- /package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Inspector/Settings.tsx +0 -0
- /package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Render/Arguments/ObjectEntity.tsx +0 -0
- /package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Render/Arguments/ValueCell.tsx +0 -0
- /package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Render/Arguments/index.tsx +0 -0
- /package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Render/ErrorResponse.tsx +0 -0
- /package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Render/KeyValueEditor.tsx +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 2.0.0-next.63](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.62...v2.0.0-next.63)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2025-11-15**</sup>
|
|
8
|
+
|
|
9
|
+
#### ✨ Features
|
|
10
|
+
|
|
11
|
+
- **misc**: Show orphaned tool message and support delete tool message.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's improved
|
|
19
|
+
|
|
20
|
+
- **misc**: Show orphaned tool message and support delete tool message, closes [#10232](https://github.com/lobehub/lobe-chat/issues/10232) ([38cfd26](https://github.com/lobehub/lobe-chat/commit/38cfd26))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
5
30
|
## [Version 2.0.0-next.62](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.61...v2.0.0-next.62)
|
|
6
31
|
|
|
7
32
|
<sup>Released on **2025-11-15**</sup>
|
package/changelog/v1.json
CHANGED
package/locales/ar/plugin.json
CHANGED
|
@@ -236,6 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
"inspector": {
|
|
238
238
|
"args": "عرض قائمة المعلمات",
|
|
239
|
+
"delete": "حذف استدعاء الأداة",
|
|
240
|
+
"orphanedToolCall": "قد تكون رسالة استدعاء الأداة هذه معزولة بسبب ظروف غير طبيعية، مما قد يؤثر على تنفيذ الوكيل بشكل صحيح. يُرجى إزالتها.",
|
|
239
241
|
"pluginRender": "عرض واجهة الإضافة"
|
|
240
242
|
},
|
|
241
243
|
"list": {
|
|
@@ -236,6 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
"inspector": {
|
|
238
238
|
"args": "Преглед на списъка с параметри",
|
|
239
|
+
"delete": "Изтриване на извикване на инструмент",
|
|
240
|
+
"orphanedToolCall": "Това извикване на инструмент може да е станало изолирано поради необичайни причини, което може да повлияе на нормалното изпълнение на агента. Моля, премахнете го.",
|
|
239
241
|
"pluginRender": "Преглед на интерфейса на плъгина"
|
|
240
242
|
},
|
|
241
243
|
"list": {
|
|
@@ -236,6 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
"inspector": {
|
|
238
238
|
"args": "Parameterliste anzeigen",
|
|
239
|
+
"delete": "Werkzeugaufruf löschen",
|
|
240
|
+
"orphanedToolCall": "Dieser Werkzeugaufruf könnte aufgrund eines Fehlers verwaist sein, was den normalen Ablauf des Agenten beeinträchtigen kann. Bitte entfernen Sie ihn.",
|
|
239
241
|
"pluginRender": "Plugin-Oberfläche anzeigen"
|
|
240
242
|
},
|
|
241
243
|
"list": {
|
|
@@ -236,6 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
"inspector": {
|
|
238
238
|
"args": "View Argument List",
|
|
239
|
+
"delete": "Delete Tool Call",
|
|
240
|
+
"orphanedToolCall": "This tool call message may have become orphaned due to an unexpected issue, which could affect the Agent's normal operation. Please remove it.",
|
|
239
241
|
"pluginRender": "View Plugin Interface"
|
|
240
242
|
},
|
|
241
243
|
"list": {
|
|
@@ -251,13 +253,18 @@
|
|
|
251
253
|
},
|
|
252
254
|
"localSystem": {
|
|
253
255
|
"apiName": {
|
|
256
|
+
"getCommandOutput": "Get Code Output",
|
|
257
|
+
"globLocalFiles": "Match Files",
|
|
258
|
+
"grepContent": "Search Content",
|
|
259
|
+
"killCommand": "Kill Code Execution",
|
|
254
260
|
"listLocalFiles": "View File List",
|
|
255
261
|
"moveLocalFiles": "Move Files",
|
|
256
262
|
"readLocalFile": "Read File Content",
|
|
257
263
|
"renameLocalFile": "Rename",
|
|
258
264
|
"runCommand": "Run Code",
|
|
259
265
|
"searchLocalFiles": "Search Files",
|
|
260
|
-
"writeLocalFile": "Write File"
|
|
266
|
+
"writeLocalFile": "Write File",
|
|
267
|
+
"editLocalFile": "Edit File"
|
|
261
268
|
},
|
|
262
269
|
"title": "Local System"
|
|
263
270
|
},
|
|
@@ -236,6 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
"inspector": {
|
|
238
238
|
"args": "Ver lista de parámetros",
|
|
239
|
+
"delete": "Eliminar llamada a la herramienta",
|
|
240
|
+
"orphanedToolCall": "Este mensaje de llamada a la herramienta podría haberse quedado huérfano debido a circunstancias excepcionales, lo que puede afectar el funcionamiento normal del agente. Por favor, elimínelo.",
|
|
239
241
|
"pluginRender": "Ver interfaz del plugin"
|
|
240
242
|
},
|
|
241
243
|
"list": {
|
|
@@ -236,6 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
"inspector": {
|
|
238
238
|
"args": "مشاهده لیست پارامترها",
|
|
239
|
+
"delete": "حذف فراخوانی ابزار",
|
|
240
|
+
"orphanedToolCall": "این پیام فراخوانی ابزار ممکن است به دلایل غیرعادی به یک پیام یتیم تبدیل شده باشد که میتواند عملکرد عادی عامل را مختل کند. لطفاً آن را حذف کنید.",
|
|
239
241
|
"pluginRender": "مشاهده رابط افزونه"
|
|
240
242
|
},
|
|
241
243
|
"list": {
|
|
@@ -236,6 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
"inspector": {
|
|
238
238
|
"args": "Voir la liste des paramètres",
|
|
239
|
+
"delete": "Supprimer l'appel d'outil",
|
|
240
|
+
"orphanedToolCall": "Cet appel d'outil est peut-être devenu orphelin en raison d'une erreur, ce qui pourrait perturber le bon fonctionnement de l'agent. Veuillez le supprimer.",
|
|
239
241
|
"pluginRender": "Voir l'interface du plugin"
|
|
240
242
|
},
|
|
241
243
|
"list": {
|
|
@@ -236,6 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
"inspector": {
|
|
238
238
|
"args": "Visualizza lista parametri",
|
|
239
|
+
"delete": "Elimina chiamata allo strumento",
|
|
240
|
+
"orphanedToolCall": "Questo messaggio di chiamata allo strumento potrebbe essere diventato orfano a causa di un'anomalia, il che potrebbe compromettere il corretto funzionamento dell'agente. Si consiglia di rimuoverlo.",
|
|
239
241
|
"pluginRender": "Visualizza interfaccia plugin"
|
|
240
242
|
},
|
|
241
243
|
"list": {
|
|
@@ -236,6 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
"inspector": {
|
|
238
238
|
"args": "Bekijk parameterlijst",
|
|
239
|
+
"delete": "Hulpoproep verwijderen",
|
|
240
|
+
"orphanedToolCall": "Dit hulpoproepbericht is mogelijk geïsoleerd geraakt door een onverwachte fout, wat de normale werking van de agent kan beïnvloeden. Verwijder het alstublieft.",
|
|
239
241
|
"pluginRender": "Bekijk plugin-interface"
|
|
240
242
|
},
|
|
241
243
|
"list": {
|
|
@@ -236,6 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
"inspector": {
|
|
238
238
|
"args": "Zobacz listę argumentów",
|
|
239
|
+
"delete": "Usuń wywołanie narzędzia",
|
|
240
|
+
"orphanedToolCall": "To wywołanie narzędzia mogło zostać osierocone z powodu nieoczekiwanych okoliczności, co może zakłócić prawidłowe działanie Agenta. Proszę je usunąć.",
|
|
239
241
|
"pluginRender": "Zobacz interfejs wtyczki"
|
|
240
242
|
},
|
|
241
243
|
"list": {
|
|
@@ -236,6 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
"inspector": {
|
|
238
238
|
"args": "Ver lista de parâmetros",
|
|
239
|
+
"delete": "Excluir chamada de ferramenta",
|
|
240
|
+
"orphanedToolCall": "Esta chamada de ferramenta pode ter se tornado uma mensagem órfã devido a um erro, o que pode afetar a execução normal do Agente. Por favor, remova-a.",
|
|
239
241
|
"pluginRender": "Ver interface do plugin"
|
|
240
242
|
},
|
|
241
243
|
"list": {
|
|
@@ -236,6 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
"inspector": {
|
|
238
238
|
"args": "Просмотр списка параметров",
|
|
239
|
+
"delete": "Удалить вызов инструмента",
|
|
240
|
+
"orphanedToolCall": "Этот вызов инструмента, возможно, стал изолированным из-за непредвиденных обстоятельств, что может повлиять на корректную работу агента. Пожалуйста, удалите его.",
|
|
239
241
|
"pluginRender": "Просмотр интерфейса плагина"
|
|
240
242
|
},
|
|
241
243
|
"list": {
|
|
@@ -236,6 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
"inspector": {
|
|
238
238
|
"args": "Parametre listesini görüntüle",
|
|
239
|
+
"delete": "Araç çağrısını sil",
|
|
240
|
+
"orphanedToolCall": "Bu araç çağrısı mesajı, beklenmeyen bir nedenle yetim kalmış olabilir ve bu durum Ajansın düzgün çalışmasını etkileyebilir. Lütfen bunu kaldırın.",
|
|
239
241
|
"pluginRender": "Eklenti arayüzünü görüntüle"
|
|
240
242
|
},
|
|
241
243
|
"list": {
|
|
@@ -236,6 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
"inspector": {
|
|
238
238
|
"args": "Xem danh sách tham số",
|
|
239
|
+
"delete": "Xoá lệnh gọi công cụ",
|
|
240
|
+
"orphanedToolCall": "Lệnh gọi công cụ này có thể đã trở thành một tin nhắn bị cô lập do sự cố bất thường, điều này có thể ảnh hưởng đến quá trình thực thi bình thường của Tác nhân. Vui lòng xoá nó.",
|
|
239
241
|
"pluginRender": "Xem giao diện plugin"
|
|
240
242
|
},
|
|
241
243
|
"list": {
|
|
@@ -236,6 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
"inspector": {
|
|
238
238
|
"args": "查看参数列表",
|
|
239
|
+
"delete": "删除工具调用",
|
|
240
|
+
"orphanedToolCall": "该工具调用消息可能因异常原因成为孤立消息,这会影响 Agent 的正常执行,请将其移除",
|
|
239
241
|
"pluginRender": "查看插件界面"
|
|
240
242
|
},
|
|
241
243
|
"list": {
|
|
@@ -251,13 +253,18 @@
|
|
|
251
253
|
},
|
|
252
254
|
"localSystem": {
|
|
253
255
|
"apiName": {
|
|
256
|
+
"getCommandOutput": "获取代码输出",
|
|
257
|
+
"globLocalFiles": "匹配搜索文件",
|
|
258
|
+
"grepContent": "搜索内容",
|
|
259
|
+
"killCommand": "终止代码执行",
|
|
254
260
|
"listLocalFiles": "查看文件列表",
|
|
255
261
|
"moveLocalFiles": "移动文件",
|
|
256
262
|
"readLocalFile": "读取文件内容",
|
|
257
263
|
"renameLocalFile": "重命名",
|
|
258
264
|
"runCommand": "执行代码",
|
|
259
265
|
"searchLocalFiles": "搜索文件",
|
|
260
|
-
"writeLocalFile": "写入文件"
|
|
266
|
+
"writeLocalFile": "写入文件",
|
|
267
|
+
"editLocalFile": "编辑文件"
|
|
261
268
|
},
|
|
262
269
|
"title": "本地系统"
|
|
263
270
|
},
|
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.63",
|
|
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",
|
|
@@ -12,7 +12,6 @@ import FileChunks from './FileChunks';
|
|
|
12
12
|
import IntentUnderstanding from './IntentUnderstanding';
|
|
13
13
|
import Reasoning from './Reasoning';
|
|
14
14
|
import SearchGrounding from './SearchGrounding';
|
|
15
|
-
import Tool from './Tool';
|
|
16
15
|
|
|
17
16
|
export const AssistantMessageContent = memo<
|
|
18
17
|
UIChatMessage & {
|
|
@@ -67,23 +66,6 @@ export const AssistantMessageContent = memo<
|
|
|
67
66
|
/>
|
|
68
67
|
)}
|
|
69
68
|
{showImageItems && <ImageFileListViewer items={imageList} />}
|
|
70
|
-
{tools && (
|
|
71
|
-
<Flexbox gap={8}>
|
|
72
|
-
{tools.map((toolCall, index) => (
|
|
73
|
-
<Tool
|
|
74
|
-
apiName={toolCall.apiName}
|
|
75
|
-
arguments={toolCall.arguments}
|
|
76
|
-
id={toolCall.id}
|
|
77
|
-
identifier={toolCall.identifier}
|
|
78
|
-
index={index}
|
|
79
|
-
key={toolCall.id}
|
|
80
|
-
messageId={id}
|
|
81
|
-
payload={toolCall}
|
|
82
|
-
type={toolCall.type}
|
|
83
|
-
/>
|
|
84
|
-
))}
|
|
85
|
-
</Flexbox>
|
|
86
|
-
)}
|
|
87
69
|
</Flexbox>
|
|
88
70
|
);
|
|
89
71
|
});
|
|
@@ -1,13 +1,23 @@
|
|
|
1
|
+
import { ToolIntervention } from '@lobechat/types';
|
|
1
2
|
import { ActionIcon, Icon, Tooltip } from '@lobehub/ui';
|
|
2
3
|
import { createStyles } from 'antd-style';
|
|
3
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
Ban,
|
|
6
|
+
Check,
|
|
7
|
+
LayoutPanelTop,
|
|
8
|
+
LogsIcon,
|
|
9
|
+
LucideBug,
|
|
10
|
+
LucideBugOff,
|
|
11
|
+
Trash2,
|
|
12
|
+
X,
|
|
13
|
+
} from 'lucide-react';
|
|
4
14
|
import { CSSProperties, memo, useState } from 'react';
|
|
5
15
|
import { useTranslation } from 'react-i18next';
|
|
6
16
|
import { Flexbox } from 'react-layout-kit';
|
|
7
17
|
|
|
8
18
|
import { LOADING_FLAT } from '@/const/message';
|
|
19
|
+
import { useChatStore } from '@/store/chat';
|
|
9
20
|
import { shinyTextStylish } from '@/styles/loading';
|
|
10
|
-
import { ToolIntervention } from '@/types/message';
|
|
11
21
|
|
|
12
22
|
import Debug from './Debug';
|
|
13
23
|
import Settings from './Settings';
|
|
@@ -63,12 +73,12 @@ export const useStyles = createStyles(({ css, token, cx }) => ({
|
|
|
63
73
|
interface InspectorProps {
|
|
64
74
|
apiName: string;
|
|
65
75
|
arguments?: string;
|
|
76
|
+
assistantMessageId: string;
|
|
66
77
|
hidePluginUI?: boolean;
|
|
67
78
|
id: string;
|
|
68
79
|
identifier: string;
|
|
69
80
|
index: number;
|
|
70
81
|
intervention?: ToolIntervention;
|
|
71
|
-
messageId: string;
|
|
72
82
|
result?: { content: string | null; error?: any; state?: any };
|
|
73
83
|
setShowPluginRender: (show: boolean) => void;
|
|
74
84
|
setShowRender: (show: boolean) => void;
|
|
@@ -81,7 +91,7 @@ interface InspectorProps {
|
|
|
81
91
|
|
|
82
92
|
const Inspectors = memo<InspectorProps>(
|
|
83
93
|
({
|
|
84
|
-
|
|
94
|
+
assistantMessageId,
|
|
85
95
|
index,
|
|
86
96
|
identifier,
|
|
87
97
|
apiName,
|
|
@@ -100,6 +110,8 @@ const Inspectors = memo<InspectorProps>(
|
|
|
100
110
|
|
|
101
111
|
const [showDebug, setShowDebug] = useState(false);
|
|
102
112
|
|
|
113
|
+
const [deleteAssistantMessage] = useChatStore((s) => [s.deleteAssistantMessage]);
|
|
114
|
+
|
|
103
115
|
const hasError = !!result?.error;
|
|
104
116
|
const hasSuccessResult = !!result?.content && result.content !== LOADING_FLAT;
|
|
105
117
|
|
|
@@ -128,7 +140,7 @@ const Inspectors = memo<InspectorProps>(
|
|
|
128
140
|
identifier={identifier}
|
|
129
141
|
index={index}
|
|
130
142
|
isLoading={isTitleLoading}
|
|
131
|
-
messageId={
|
|
143
|
+
messageId={assistantMessageId}
|
|
132
144
|
toolCallId={id}
|
|
133
145
|
/>
|
|
134
146
|
</Flexbox>
|
|
@@ -152,6 +164,15 @@ const Inspectors = memo<InspectorProps>(
|
|
|
152
164
|
size={'small'}
|
|
153
165
|
title={t(showDebug ? 'debug.off' : 'debug.on')}
|
|
154
166
|
/>
|
|
167
|
+
<ActionIcon
|
|
168
|
+
icon={Trash2}
|
|
169
|
+
onClick={() => {
|
|
170
|
+
deleteAssistantMessage(assistantMessageId);
|
|
171
|
+
}}
|
|
172
|
+
size={'small'}
|
|
173
|
+
title={t('inspector.delete')}
|
|
174
|
+
/>
|
|
175
|
+
|
|
155
176
|
<Settings id={identifier} />
|
|
156
177
|
</Flexbox>
|
|
157
178
|
{hasResult && (
|
|
@@ -60,11 +60,11 @@ const Tool = memo<GroupToolProps>(
|
|
|
60
60
|
<Inspectors
|
|
61
61
|
apiName={apiName}
|
|
62
62
|
arguments={requestArgs}
|
|
63
|
+
assistantMessageId={assistantMessageId}
|
|
63
64
|
id={id}
|
|
64
65
|
identifier={identifier}
|
|
65
66
|
index={index}
|
|
66
67
|
intervention={intervention}
|
|
67
|
-
messageId={assistantMessageId}
|
|
68
68
|
result={result}
|
|
69
69
|
setShowPluginRender={setShowCustomPluginUI}
|
|
70
70
|
setShowRender={setShowToolDetail}
|
|
@@ -6,8 +6,6 @@ import { memo, useMemo } from 'react';
|
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { Flexbox } from 'react-layout-kit';
|
|
8
8
|
|
|
9
|
-
import { useChatStore } from '@/store/chat';
|
|
10
|
-
import { messageStateSelectors } from '@/store/chat/selectors';
|
|
11
9
|
import { pluginHelpers, useToolStore } from '@/store/tool';
|
|
12
10
|
import { toolSelectors } from '@/store/tool/selectors';
|
|
13
11
|
import { shinyTextStylish } from '@/styles/loading';
|
|
@@ -43,10 +41,6 @@ const ToolTitle = memo<ToolTitleProps>(({ identifier, messageId, index, apiName,
|
|
|
43
41
|
const { t } = useTranslation('plugin');
|
|
44
42
|
const { styles } = useStyles();
|
|
45
43
|
|
|
46
|
-
const isLoading = useChatStore(
|
|
47
|
-
messageStateSelectors.isToolApiNameShining(messageId, index, toolCallId),
|
|
48
|
-
);
|
|
49
|
-
|
|
50
44
|
const pluginMeta = useToolStore(toolSelectors.getMetaById(identifier), isEqual);
|
|
51
45
|
|
|
52
46
|
const plugins = useMemo(
|
|
@@ -84,7 +78,7 @@ const ToolTitle = memo<ToolTitleProps>(({ identifier, messageId, index, apiName,
|
|
|
84
78
|
const pluginTitle = pluginHelpers.getPluginTitle(pluginMeta) ?? t('unknownPlugin');
|
|
85
79
|
|
|
86
80
|
return (
|
|
87
|
-
<Flexbox align={'center'}
|
|
81
|
+
<Flexbox align={'center'} gap={6} horizontal>
|
|
88
82
|
<div>{pluginTitle}</div> <Icon icon={ChevronRight} />
|
|
89
83
|
<span className={styles.apiName}>{apiName}</span>
|
|
90
84
|
</Flexbox>
|
|
@@ -68,10 +68,8 @@ interface InspectorProps {
|
|
|
68
68
|
messageId: string;
|
|
69
69
|
payload: object;
|
|
70
70
|
setShowPluginRender: (show: boolean) => void;
|
|
71
|
-
setShowRender: (show: boolean) => void;
|
|
72
71
|
showPluginRender: boolean;
|
|
73
72
|
showPortal?: boolean;
|
|
74
|
-
showRender: boolean;
|
|
75
73
|
style?: CSSProperties;
|
|
76
74
|
}
|
|
77
75
|
|
|
@@ -83,9 +81,7 @@ const Inspectors = memo<InspectorProps>(
|
|
|
83
81
|
apiName,
|
|
84
82
|
id,
|
|
85
83
|
arguments: requestArgs,
|
|
86
|
-
showRender,
|
|
87
84
|
payload,
|
|
88
|
-
setShowRender,
|
|
89
85
|
showPluginRender,
|
|
90
86
|
setShowPluginRender,
|
|
91
87
|
hidePluginUI = false,
|
|
@@ -98,16 +94,7 @@ const Inspectors = memo<InspectorProps>(
|
|
|
98
94
|
return (
|
|
99
95
|
<Flexbox className={styles.container} gap={4}>
|
|
100
96
|
<Flexbox align={'center'} distribution={'space-between'} gap={8} horizontal>
|
|
101
|
-
<Flexbox
|
|
102
|
-
align={'center'}
|
|
103
|
-
className={styles.tool}
|
|
104
|
-
gap={8}
|
|
105
|
-
horizontal
|
|
106
|
-
onClick={() => {
|
|
107
|
-
setShowRender(!showRender);
|
|
108
|
-
}}
|
|
109
|
-
paddingInline={4}
|
|
110
|
-
>
|
|
97
|
+
<Flexbox align={'center'} className={styles.tool} gap={8} horizontal paddingInline={4}>
|
|
111
98
|
<ToolTitle
|
|
112
99
|
apiName={apiName}
|
|
113
100
|
identifier={identifier}
|
|
@@ -117,7 +104,7 @@ const Inspectors = memo<InspectorProps>(
|
|
|
117
104
|
/>
|
|
118
105
|
</Flexbox>
|
|
119
106
|
<Flexbox className={styles.actions} horizontal>
|
|
120
|
-
{
|
|
107
|
+
{!hidePluginUI && (
|
|
121
108
|
<ActionIcon
|
|
122
109
|
icon={showPluginRender ? LogsIcon : LayoutPanelTop}
|
|
123
110
|
onClick={() => {
|
|
@@ -7,11 +7,11 @@ import { memo, useCallback, useEffect, useState } from 'react';
|
|
|
7
7
|
import { useTranslation } from 'react-i18next';
|
|
8
8
|
import { Flexbox } from 'react-layout-kit';
|
|
9
9
|
|
|
10
|
-
import PluginResult from '@/features/Conversation/Messages/Assistant/Tool/Inspector/PluginResult';
|
|
11
10
|
import PluginRender from '@/features/PluginsUI/Render';
|
|
12
11
|
import { useChatStore } from '@/store/chat';
|
|
13
12
|
import { messageStateSelectors } from '@/store/chat/selectors';
|
|
14
13
|
|
|
14
|
+
import PluginResult from '../Inspector/PluginResult';
|
|
15
15
|
import Arguments from './Arguments';
|
|
16
16
|
import KeyValueEditor from './KeyValueEditor';
|
|
17
17
|
|
package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Render/PluginSettings.tsx
RENAMED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ChatPluginPayload } from '@lobechat/types';
|
|
2
1
|
import { Avatar, Button } from '@lobehub/ui';
|
|
3
2
|
import { Divider } from 'antd';
|
|
4
3
|
import { useTheme } from 'antd-style';
|
|
@@ -11,8 +10,9 @@ import PluginSettingsConfig from '@/features/PluginSettings';
|
|
|
11
10
|
import { useChatStore } from '@/store/chat';
|
|
12
11
|
import { pluginHelpers, useToolStore } from '@/store/tool';
|
|
13
12
|
import { pluginSelectors } from '@/store/tool/selectors';
|
|
13
|
+
import { ChatPluginPayload } from '@/types/index';
|
|
14
14
|
|
|
15
|
-
import { ErrorActionContainer, useStyles } from '
|
|
15
|
+
import { ErrorActionContainer, useStyles } from '../../../Error/style';
|
|
16
16
|
|
|
17
17
|
interface PluginSettingsProps {
|
|
18
18
|
id: string;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { LOADING_FLAT } from '@lobechat/const';
|
|
2
1
|
import { Suspense, memo } from 'react';
|
|
3
2
|
|
|
4
3
|
import { useChatStore } from '@/store/chat';
|
|
@@ -6,11 +5,8 @@ import { dbMessageSelectors, messageStateSelectors } from '@/store/chat/selector
|
|
|
6
5
|
|
|
7
6
|
import CustomRender from './CustomRender';
|
|
8
7
|
import ErrorResponse from './ErrorResponse';
|
|
9
|
-
import LoadingPlaceholder from './LoadingPlaceholder';
|
|
10
8
|
|
|
11
9
|
interface RenderProps {
|
|
12
|
-
apiName: string;
|
|
13
|
-
identifier: string;
|
|
14
10
|
messageId: string;
|
|
15
11
|
requestArgs?: string;
|
|
16
12
|
setShowPluginRender: (show: boolean) => void;
|
|
@@ -20,16 +16,7 @@ interface RenderProps {
|
|
|
20
16
|
}
|
|
21
17
|
|
|
22
18
|
const Render = memo<RenderProps>(
|
|
23
|
-
({
|
|
24
|
-
toolCallId,
|
|
25
|
-
toolIndex,
|
|
26
|
-
messageId,
|
|
27
|
-
requestArgs,
|
|
28
|
-
showPluginRender,
|
|
29
|
-
setShowPluginRender,
|
|
30
|
-
identifier,
|
|
31
|
-
apiName,
|
|
32
|
-
}) => {
|
|
19
|
+
({ toolCallId, toolIndex, messageId, requestArgs, showPluginRender, setShowPluginRender }) => {
|
|
33
20
|
const loading = useChatStore(messageStateSelectors.isToolCallStreaming(messageId, toolIndex));
|
|
34
21
|
const toolMessage = useChatStore(dbMessageSelectors.getDbMessageByToolCallId(toolCallId));
|
|
35
22
|
|
|
@@ -40,24 +27,8 @@ const Render = memo<RenderProps>(
|
|
|
40
27
|
return <ErrorResponse {...toolMessage.error} id={messageId} plugin={toolMessage.plugin} />;
|
|
41
28
|
}
|
|
42
29
|
|
|
43
|
-
const placeholder = (
|
|
44
|
-
<LoadingPlaceholder
|
|
45
|
-
apiName={apiName}
|
|
46
|
-
identifier={identifier}
|
|
47
|
-
loading
|
|
48
|
-
requestArgs={requestArgs}
|
|
49
|
-
/>
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
// 如果是 LOADING_FLAT 则说明还在加载中
|
|
53
|
-
// 而 standalone 模式的插件 content 应该始终是 LOADING_FLAT
|
|
54
|
-
const inPlaceholder =
|
|
55
|
-
toolMessage.content === LOADING_FLAT && toolMessage.plugin?.type !== 'standalone';
|
|
56
|
-
|
|
57
|
-
if (inPlaceholder) return placeholder;
|
|
58
|
-
|
|
59
30
|
return (
|
|
60
|
-
<Suspense
|
|
31
|
+
<Suspense>
|
|
61
32
|
<CustomRender
|
|
62
33
|
{...toolMessage}
|
|
63
34
|
requestArgs={requestArgs}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { CSSProperties, memo, useState } from 'react';
|
|
2
|
+
import { Flexbox } from 'react-layout-kit';
|
|
3
|
+
|
|
4
|
+
import Inspectors from './Inspector';
|
|
5
|
+
import Render from './Render';
|
|
6
|
+
|
|
7
|
+
export interface InspectorProps {
|
|
8
|
+
apiName: string;
|
|
9
|
+
arguments?: string;
|
|
10
|
+
identifier: string;
|
|
11
|
+
index: number;
|
|
12
|
+
messageId: string;
|
|
13
|
+
payload: object;
|
|
14
|
+
style?: CSSProperties;
|
|
15
|
+
toolCallId: string;
|
|
16
|
+
type?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const Tool = memo<InspectorProps>(
|
|
20
|
+
({ arguments: requestArgs, apiName, messageId, toolCallId, index, identifier, payload }) => {
|
|
21
|
+
const [showPluginRender, setShowPluginRender] = useState(false);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<Flexbox gap={8} style={{ paddingBottom: 12 }}>
|
|
25
|
+
<Inspectors
|
|
26
|
+
apiName={apiName}
|
|
27
|
+
arguments={requestArgs}
|
|
28
|
+
id={toolCallId}
|
|
29
|
+
identifier={identifier}
|
|
30
|
+
index={index}
|
|
31
|
+
messageId={messageId}
|
|
32
|
+
payload={payload}
|
|
33
|
+
setShowPluginRender={setShowPluginRender}
|
|
34
|
+
showPluginRender={showPluginRender}
|
|
35
|
+
/>
|
|
36
|
+
<Render
|
|
37
|
+
messageId={messageId}
|
|
38
|
+
requestArgs={requestArgs}
|
|
39
|
+
setShowPluginRender={setShowPluginRender}
|
|
40
|
+
showPluginRender={showPluginRender}
|
|
41
|
+
toolCallId={toolCallId}
|
|
42
|
+
toolIndex={index}
|
|
43
|
+
/>
|
|
44
|
+
</Flexbox>
|
|
45
|
+
);
|
|
46
|
+
},
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
Tool.displayName = 'AssistantTool';
|
|
50
|
+
|
|
51
|
+
export default Tool;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Alert } from '@lobehub/ui';
|
|
2
|
+
import { Button } from 'antd';
|
|
3
|
+
import isEqual from 'fast-deep-equal';
|
|
4
|
+
import { memo, useState } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import { Flexbox } from 'react-layout-kit';
|
|
7
|
+
|
|
8
|
+
import { useChatStore } from '@/store/chat';
|
|
9
|
+
import { dbMessageSelectors } from '@/store/chat/selectors';
|
|
10
|
+
import { UIChatMessage } from '@/types/message';
|
|
11
|
+
|
|
12
|
+
import ToolItem from './ToolItem';
|
|
13
|
+
|
|
14
|
+
interface ToolMessageProps {
|
|
15
|
+
id: string;
|
|
16
|
+
index: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const Tool = memo<ToolMessageProps>(({ id, index }) => {
|
|
20
|
+
const { t } = useTranslation('plugin');
|
|
21
|
+
const item = useChatStore(dbMessageSelectors.getDbMessageById(id), isEqual) as UIChatMessage;
|
|
22
|
+
const deleteToolMessage = useChatStore((s) => s.deleteToolMessage);
|
|
23
|
+
const [loading, setLoading] = useState(false);
|
|
24
|
+
|
|
25
|
+
const handleDelete = async () => {
|
|
26
|
+
setLoading(true);
|
|
27
|
+
try {
|
|
28
|
+
await deleteToolMessage(id);
|
|
29
|
+
} finally {
|
|
30
|
+
setLoading(false);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<Flexbox gap={4} paddingBlock={12} paddingInline={12}>
|
|
36
|
+
<Alert
|
|
37
|
+
action={
|
|
38
|
+
<Button loading={loading} onClick={handleDelete} size={'small'} type={'primary'}>
|
|
39
|
+
{t('inspector.delete')}
|
|
40
|
+
</Button>
|
|
41
|
+
}
|
|
42
|
+
message={t('inspector.orphanedToolCall')}
|
|
43
|
+
type={'warning'}
|
|
44
|
+
variant={'borderless'}
|
|
45
|
+
/>
|
|
46
|
+
{item.plugin && (
|
|
47
|
+
<ToolItem
|
|
48
|
+
{...item.plugin}
|
|
49
|
+
index={index}
|
|
50
|
+
messageId={id}
|
|
51
|
+
payload={item.plugin || {}}
|
|
52
|
+
toolCallId={item.tool_call_id!}
|
|
53
|
+
/>
|
|
54
|
+
)}
|
|
55
|
+
</Flexbox>
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
export default Tool;
|
|
@@ -18,6 +18,7 @@ import { InPortalThreadContext } from '../context/InPortalThreadContext';
|
|
|
18
18
|
import AssistantMessage from './Assistant';
|
|
19
19
|
import GroupMessage from './Group';
|
|
20
20
|
import SupervisorMessage from './Supervisor';
|
|
21
|
+
import ToolMessage from './Tool';
|
|
21
22
|
import UserMessage from './User';
|
|
22
23
|
|
|
23
24
|
const useStyles = createStyles(({ css, prefixCls }) => ({
|
|
@@ -133,6 +134,10 @@ const Item = memo<ChatListItemProps>(
|
|
|
133
134
|
return <GroupMessage disableEditing={disableEditing} id={id} index={index} />;
|
|
134
135
|
}
|
|
135
136
|
|
|
137
|
+
case 'tool': {
|
|
138
|
+
return <ToolMessage id={id} index={index} />;
|
|
139
|
+
}
|
|
140
|
+
|
|
136
141
|
case 'supervisor': {
|
|
137
142
|
return <SupervisorMessage disableEditing={disableEditing} id={id} index={index} />;
|
|
138
143
|
}
|
|
@@ -12,7 +12,7 @@ import { useIsMobile } from '@/hooks/useIsMobile';
|
|
|
12
12
|
import { useAgentStore } from '@/store/agent';
|
|
13
13
|
import { agentSelectors } from '@/store/agent/selectors';
|
|
14
14
|
import { useChatStore } from '@/store/chat';
|
|
15
|
-
import {
|
|
15
|
+
import { dbMessageSelectors, topicSelectors } from '@/store/chat/selectors';
|
|
16
16
|
|
|
17
17
|
import { useStyles } from '../style';
|
|
18
18
|
import Preview from './Preview';
|
|
@@ -50,7 +50,7 @@ const ShareImage = memo(() => {
|
|
|
50
50
|
];
|
|
51
51
|
|
|
52
52
|
const systemRole = useAgentStore(agentSelectors.currentAgentSystemRole);
|
|
53
|
-
const messages = useChatStore(
|
|
53
|
+
const messages = useChatStore(dbMessageSelectors.activeDbMessages, isEqual);
|
|
54
54
|
const data = generateMessages({ ...fieldValue, messages, systemRole });
|
|
55
55
|
const content = JSON.stringify(data, null, 2);
|
|
56
56
|
|
|
@@ -237,6 +237,9 @@ export default {
|
|
|
237
237
|
},
|
|
238
238
|
inspector: {
|
|
239
239
|
args: '查看参数列表',
|
|
240
|
+
delete: '删除工具调用',
|
|
241
|
+
orphanedToolCall:
|
|
242
|
+
'该工具调用消息可能因异常原因成为孤立消息,这会影响 Agent 的正常执行,请将其移除',
|
|
240
243
|
pluginRender: '查看插件界面',
|
|
241
244
|
},
|
|
242
245
|
list: {
|
|
@@ -252,6 +255,11 @@ export default {
|
|
|
252
255
|
},
|
|
253
256
|
localSystem: {
|
|
254
257
|
apiName: {
|
|
258
|
+
editLocalFile: '编辑文件',
|
|
259
|
+
getCommandOutput: '获取代码输出',
|
|
260
|
+
globLocalFiles: '匹配搜索文件',
|
|
261
|
+
grepContent: '搜索内容',
|
|
262
|
+
killCommand: '终止代码执行',
|
|
255
263
|
listLocalFiles: '查看文件列表',
|
|
256
264
|
moveLocalFiles: '移动文件',
|
|
257
265
|
readLocalFile: '读取文件内容',
|
|
@@ -227,13 +227,16 @@ describe('chatMessage actions', () => {
|
|
|
227
227
|
expect(replaceMessagesSpy).toHaveBeenCalledWith(mockMessages);
|
|
228
228
|
});
|
|
229
229
|
|
|
230
|
-
it('deleteMessage should remove
|
|
230
|
+
it('deleteMessage should remove the message only', async () => {
|
|
231
231
|
const { result } = renderHook(() => useChatStore());
|
|
232
232
|
const messageId = 'message-id';
|
|
233
233
|
const removeMessagesSpy = vi.spyOn(messageService, 'removeMessages');
|
|
234
|
-
const mockMessages = [
|
|
234
|
+
const mockMessages = [
|
|
235
|
+
{ id: '2', tool_call_id: 'tool1', role: 'tool' },
|
|
236
|
+
{ id: '3', tool_call_id: 'tool2', role: 'tool' },
|
|
237
|
+
] as any;
|
|
235
238
|
|
|
236
|
-
// Mock the service to return messages
|
|
239
|
+
// Mock the service to return remaining messages (orphaned tool messages)
|
|
237
240
|
(messageService.removeMessages as Mock).mockResolvedValue({
|
|
238
241
|
success: true,
|
|
239
242
|
messages: mockMessages,
|
|
@@ -258,7 +261,8 @@ describe('chatMessage actions', () => {
|
|
|
258
261
|
await result.current.deleteMessage(messageId);
|
|
259
262
|
});
|
|
260
263
|
|
|
261
|
-
|
|
264
|
+
// Only the message itself should be deleted, tool messages remain as orphaned
|
|
265
|
+
expect(removeMessagesSpy).toHaveBeenCalledWith([messageId], {
|
|
262
266
|
sessionId: 'session-id',
|
|
263
267
|
topicId: undefined,
|
|
264
268
|
});
|
|
@@ -41,6 +41,7 @@ export interface MessageOptimisticUpdateAction {
|
|
|
41
41
|
* delete the message content with optimistic update
|
|
42
42
|
*/
|
|
43
43
|
optimisticDeleteMessage: (id: string) => Promise<void>;
|
|
44
|
+
optimisticDeleteMessages: (ids: string[]) => Promise<void>;
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
47
|
* update the message content with optimistic update
|
|
@@ -154,6 +155,17 @@ export const messageOptimisticUpdate: StateCreator<
|
|
|
154
155
|
}
|
|
155
156
|
},
|
|
156
157
|
|
|
158
|
+
optimisticDeleteMessages: async (ids) => {
|
|
159
|
+
get().internal_dispatchMessage({ ids, type: 'deleteMessages' });
|
|
160
|
+
const result = await messageService.removeMessages(ids, {
|
|
161
|
+
sessionId: get().activeId,
|
|
162
|
+
topicId: get().activeTopicId,
|
|
163
|
+
});
|
|
164
|
+
if (result?.success && result.messages) {
|
|
165
|
+
get().replaceMessages(result.messages);
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
|
|
157
169
|
optimisticUpdateMessageContent: async (id, content, extra) => {
|
|
158
170
|
const {
|
|
159
171
|
internal_dispatchMessage,
|
|
@@ -31,6 +31,7 @@ export interface MessagePublicApiAction {
|
|
|
31
31
|
*/
|
|
32
32
|
clearMessage: () => Promise<void>;
|
|
33
33
|
deleteMessage: (id: string) => Promise<void>;
|
|
34
|
+
deleteAssistantMessage: (id: string) => Promise<void>;
|
|
34
35
|
deleteDBMessage: (id: string) => Promise<void>;
|
|
35
36
|
deleteToolMessage: (id: string) => Promise<void>;
|
|
36
37
|
clearAllMessages: () => Promise<void>;
|
|
@@ -97,12 +98,28 @@ export const messagePublicApi: StateCreator<
|
|
|
97
98
|
}
|
|
98
99
|
},
|
|
99
100
|
|
|
101
|
+
deleteAssistantMessage: async (id) => {
|
|
102
|
+
const message = dbMessageSelectors.getDbMessageById(id)(get());
|
|
103
|
+
if (!message) return;
|
|
104
|
+
|
|
105
|
+
let ids = [message.id];
|
|
106
|
+
if (message.tools) {
|
|
107
|
+
const allMessages = dbMessageSelectors.activeDbMessages(get());
|
|
108
|
+
|
|
109
|
+
const toolMessageIds = message.tools.flatMap((tool) => {
|
|
110
|
+
const messages = allMessages.filter((m) => m.tool_call_id === tool.id);
|
|
111
|
+
return messages.map((m) => m.id);
|
|
112
|
+
});
|
|
113
|
+
ids = ids.concat(toolMessageIds);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
await get().optimisticDeleteMessages(ids);
|
|
117
|
+
},
|
|
100
118
|
deleteMessage: async (id) => {
|
|
101
119
|
const message = displayMessageSelectors.getDisplayMessageById(id)(get());
|
|
102
120
|
if (!message) return;
|
|
103
121
|
|
|
104
122
|
let ids = [message.id];
|
|
105
|
-
const allMessages = displayMessageSelectors.activeDisplayMessages(get());
|
|
106
123
|
|
|
107
124
|
// Handle assistantGroup messages: delete all child blocks and tool results
|
|
108
125
|
if (message.role === 'assistantGroup' && message.children) {
|
|
@@ -117,23 +134,8 @@ export const messagePublicApi: StateCreator<
|
|
|
117
134
|
});
|
|
118
135
|
ids = ids.concat(toolResultIds);
|
|
119
136
|
}
|
|
120
|
-
// Handle regular messages with tools: find and delete related tool messages
|
|
121
|
-
else if (message.tools) {
|
|
122
|
-
const toolMessageIds = message.tools.flatMap((tool) => {
|
|
123
|
-
const messages = allMessages.filter((m) => m.tool_call_id === tool.id);
|
|
124
|
-
return messages.map((m) => m.id);
|
|
125
|
-
});
|
|
126
|
-
ids = ids.concat(toolMessageIds);
|
|
127
|
-
}
|
|
128
137
|
|
|
129
|
-
get().
|
|
130
|
-
const result = await messageService.removeMessages(ids, {
|
|
131
|
-
sessionId: get().activeId,
|
|
132
|
-
topicId: get().activeTopicId,
|
|
133
|
-
});
|
|
134
|
-
if (result?.success && result.messages) {
|
|
135
|
-
get().replaceMessages(result.messages);
|
|
136
|
-
}
|
|
138
|
+
await get().optimisticDeleteMessages(ids);
|
|
137
139
|
},
|
|
138
140
|
|
|
139
141
|
deleteDBMessage: async (id) => {
|
|
@@ -203,6 +203,33 @@ export const LocalSystemManifest: BuiltinToolManifest = {
|
|
|
203
203
|
type: 'object',
|
|
204
204
|
},
|
|
205
205
|
},
|
|
206
|
+
{
|
|
207
|
+
description:
|
|
208
|
+
'Perform exact string replacements in files. Must read the file first before editing.',
|
|
209
|
+
name: LocalSystemApiName.editLocalFile,
|
|
210
|
+
parameters: {
|
|
211
|
+
properties: {
|
|
212
|
+
file_path: {
|
|
213
|
+
description: 'The absolute path to the file to modify',
|
|
214
|
+
type: 'string',
|
|
215
|
+
},
|
|
216
|
+
new_string: {
|
|
217
|
+
description: 'The text to replace with (must differ from old_string)',
|
|
218
|
+
type: 'string',
|
|
219
|
+
},
|
|
220
|
+
old_string: {
|
|
221
|
+
description: 'The exact text to replace',
|
|
222
|
+
type: 'string',
|
|
223
|
+
},
|
|
224
|
+
replace_all: {
|
|
225
|
+
description: 'Replace all occurrences of old_string (default: false)',
|
|
226
|
+
type: 'boolean',
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
required: ['file_path', 'old_string', 'new_string'],
|
|
230
|
+
type: 'object',
|
|
231
|
+
},
|
|
232
|
+
},
|
|
206
233
|
{
|
|
207
234
|
description:
|
|
208
235
|
'Execute a shell command and return its output. Supports both synchronous and background execution with timeout control.',
|
|
@@ -349,33 +376,6 @@ export const LocalSystemManifest: BuiltinToolManifest = {
|
|
|
349
376
|
type: 'object',
|
|
350
377
|
},
|
|
351
378
|
},
|
|
352
|
-
{
|
|
353
|
-
description:
|
|
354
|
-
'Perform exact string replacements in files. Must read the file first before editing.',
|
|
355
|
-
name: LocalSystemApiName.editLocalFile,
|
|
356
|
-
parameters: {
|
|
357
|
-
properties: {
|
|
358
|
-
file_path: {
|
|
359
|
-
description: 'The absolute path to the file to modify',
|
|
360
|
-
type: 'string',
|
|
361
|
-
},
|
|
362
|
-
new_string: {
|
|
363
|
-
description: 'The text to replace with (must differ from old_string)',
|
|
364
|
-
type: 'string',
|
|
365
|
-
},
|
|
366
|
-
old_string: {
|
|
367
|
-
description: 'The exact text to replace',
|
|
368
|
-
type: 'string',
|
|
369
|
-
},
|
|
370
|
-
replace_all: {
|
|
371
|
-
description: 'Replace all occurrences of old_string (default: false)',
|
|
372
|
-
type: 'boolean',
|
|
373
|
-
},
|
|
374
|
-
},
|
|
375
|
-
required: ['file_path', 'old_string', 'new_string'],
|
|
376
|
-
type: 'object',
|
|
377
|
-
},
|
|
378
|
-
},
|
|
379
379
|
],
|
|
380
380
|
identifier: 'lobe-local-system',
|
|
381
381
|
meta: {
|
|
@@ -19,17 +19,17 @@ You have access to a set of tools to interact with the user's local file system:
|
|
|
19
19
|
1. **listLocalFiles**: Lists files and directories in a specified path.
|
|
20
20
|
2. **readLocalFile**: Reads the content of a specified file, optionally within a line range. You can read file types such as Word, Excel, PowerPoint, PDF, and plain text files.
|
|
21
21
|
3. **writeLocalFile**: Write content to a specific file, only support plain text file like \`.text\` or \`.md\`
|
|
22
|
-
4. **
|
|
22
|
+
4. **editLocalFile**: Performs exact string replacements in files. Must read the file first before editing.
|
|
23
23
|
5. **renameLocalFile**: Renames a single file or directory in its current location.
|
|
24
24
|
6. **moveLocalFiles**: Moves multiple files or directories. Can be used for renaming during the move.
|
|
25
|
-
7. **editLocalFile**: Performs exact string replacements in files. Must read the file first before editing.
|
|
26
25
|
|
|
27
26
|
**Shell Commands:**
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
7. **runCommand**: Execute shell commands with timeout control. Supports both synchronous and background execution. When providing a description, always use the same language as the user's input.
|
|
28
|
+
8. **getCommandOutput**: Retrieve output from running background commands. Returns only new output since last check.
|
|
29
|
+
9. **killCommand**: Terminate a running background shell command by its ID.
|
|
31
30
|
|
|
32
31
|
**Search & Find:**
|
|
32
|
+
10. **searchLocalFiles**: Searches for files based on keywords and other criteria using Spotlight (macOS) or native search. Use this tool to find files if the user is unsure about the exact path.
|
|
33
33
|
11. **grepContent**: Search for content within files using regex patterns. Supports various output modes, filtering, and context lines.
|
|
34
34
|
12. **globLocalFiles**: Find files matching glob patterns (e.g., "**/*.js", "*.{ts,tsx}").
|
|
35
35
|
</core_capabilities>
|
|
@@ -37,9 +37,9 @@ You have access to a set of tools to interact with the user's local file system:
|
|
|
37
37
|
<workflow>
|
|
38
38
|
1. Understand the user's request regarding local operations (files, commands, searches).
|
|
39
39
|
2. Select the appropriate tool:
|
|
40
|
-
- File operations: listLocalFiles, readLocalFile, writeLocalFile, editLocalFile,
|
|
40
|
+
- File operations: listLocalFiles, readLocalFile, writeLocalFile, editLocalFile, renameLocalFile, moveLocalFiles
|
|
41
41
|
- Shell commands: runCommand, getCommandOutput, killCommand
|
|
42
|
-
- Search/Find: grepContent, globLocalFiles
|
|
42
|
+
- Search/Find: searchLocalFiles, grepContent, globLocalFiles
|
|
43
43
|
3. Execute the operation. **If the user mentions a common location (like Desktop, Documents, Downloads, etc.) without providing a full path, use the corresponding path from the <user_context> section.**
|
|
44
44
|
4. Present the results or confirmation.
|
|
45
45
|
</workflow>
|
package/src/features/Conversation/Messages/Assistant/Tool/Render/LoadingPlaceholder/index.tsx
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { safeParseJSON } from '@lobechat/utils';
|
|
2
|
-
import { memo } from 'react';
|
|
3
|
-
|
|
4
|
-
import { getBuiltinPlaceholder } from '@/tools/placeholders';
|
|
5
|
-
|
|
6
|
-
import Arguments from '../Arguments';
|
|
7
|
-
|
|
8
|
-
interface LoadingPlaceholderProps {
|
|
9
|
-
apiName: string;
|
|
10
|
-
identifier: string;
|
|
11
|
-
loading?: boolean;
|
|
12
|
-
requestArgs?: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const LoadingPlaceholder = memo<LoadingPlaceholderProps>(
|
|
16
|
-
({ identifier, requestArgs, apiName, loading }) => {
|
|
17
|
-
const Render = getBuiltinPlaceholder(identifier, apiName);
|
|
18
|
-
|
|
19
|
-
if (Render) {
|
|
20
|
-
return (
|
|
21
|
-
<Render apiName={apiName} args={safeParseJSON(requestArgs) || {}} identifier={identifier} />
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return <Arguments arguments={requestArgs} shine={loading} />;
|
|
26
|
-
},
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
export default LoadingPlaceholder;
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { CSSProperties, memo, useEffect, useState } from 'react';
|
|
2
|
-
import { Flexbox } from 'react-layout-kit';
|
|
3
|
-
|
|
4
|
-
import AnimatedCollapsed from '@/components/AnimatedCollapsed';
|
|
5
|
-
import { useChatStore } from '@/store/chat';
|
|
6
|
-
import { messageStateSelectors } from '@/store/chat/selectors';
|
|
7
|
-
|
|
8
|
-
import Inspectors from './Inspector';
|
|
9
|
-
import Render from './Render';
|
|
10
|
-
|
|
11
|
-
export interface InspectorProps {
|
|
12
|
-
apiName: string;
|
|
13
|
-
arguments?: string;
|
|
14
|
-
id: string;
|
|
15
|
-
identifier: string;
|
|
16
|
-
index: number;
|
|
17
|
-
messageId: string;
|
|
18
|
-
payload: object;
|
|
19
|
-
style?: CSSProperties;
|
|
20
|
-
type?: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const Tool = memo<InspectorProps>(
|
|
24
|
-
({ arguments: requestArgs, apiName, messageId, id, index, identifier, style, payload, type }) => {
|
|
25
|
-
const [showDetail, setShowDetail] = useState(type !== 'mcp');
|
|
26
|
-
const [showPluginRender, setShowPluginRender] = useState(false);
|
|
27
|
-
const isLoading = useChatStore(messageStateSelectors.isInToolsCalling(messageId, index));
|
|
28
|
-
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
if (type !== 'mcp') return;
|
|
31
|
-
|
|
32
|
-
setTimeout(
|
|
33
|
-
() => {
|
|
34
|
-
setShowDetail(isLoading);
|
|
35
|
-
},
|
|
36
|
-
isLoading ? 1 : 1500,
|
|
37
|
-
);
|
|
38
|
-
}, [isLoading]);
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<Flexbox gap={8} style={style}>
|
|
42
|
-
<Inspectors
|
|
43
|
-
apiName={apiName}
|
|
44
|
-
arguments={requestArgs}
|
|
45
|
-
// mcp don't have ui render
|
|
46
|
-
hidePluginUI={type === 'mcp'}
|
|
47
|
-
id={id}
|
|
48
|
-
identifier={identifier}
|
|
49
|
-
index={index}
|
|
50
|
-
messageId={messageId}
|
|
51
|
-
payload={payload}
|
|
52
|
-
setShowPluginRender={setShowPluginRender}
|
|
53
|
-
setShowRender={setShowDetail}
|
|
54
|
-
showPluginRender={showPluginRender}
|
|
55
|
-
showRender={showDetail}
|
|
56
|
-
/>
|
|
57
|
-
<AnimatedCollapsed open={showDetail}>
|
|
58
|
-
<Render
|
|
59
|
-
apiName={apiName}
|
|
60
|
-
identifier={identifier}
|
|
61
|
-
messageId={messageId}
|
|
62
|
-
requestArgs={requestArgs}
|
|
63
|
-
setShowPluginRender={setShowPluginRender}
|
|
64
|
-
showPluginRender={showPluginRender}
|
|
65
|
-
toolCallId={id}
|
|
66
|
-
toolIndex={index}
|
|
67
|
-
/>
|
|
68
|
-
</AnimatedCollapsed>
|
|
69
|
-
</Flexbox>
|
|
70
|
-
);
|
|
71
|
-
},
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
Tool.displayName = 'AssistantTool';
|
|
75
|
-
|
|
76
|
-
export default Tool;
|
/package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Inspector/BuiltinPluginTitle.tsx
RENAMED
|
File without changes
|
|
File without changes
|
/package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Inspector/PluginResult.tsx
RENAMED
|
File without changes
|
/package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Inspector/PluginState.tsx
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Render/Arguments/ValueCell.tsx
RENAMED
|
File without changes
|
/package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Render/Arguments/index.tsx
RENAMED
|
File without changes
|
/package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Render/ErrorResponse.tsx
RENAMED
|
File without changes
|
/package/src/features/Conversation/Messages/{Assistant/Tool → Tool}/Render/KeyValueEditor.tsx
RENAMED
|
File without changes
|