@lobehub/lobehub 2.0.0-next.51 → 2.0.0-next.53
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 +58 -0
- package/README.md +8 -8
- package/README.zh-CN.md +8 -8
- package/apps/desktop/package.json +1 -1
- package/apps/desktop/src/main/controllers/LocalFileCtr.ts +25 -5
- package/apps/desktop/src/main/controllers/__tests__/LocalFileCtr.test.ts +4 -1
- package/apps/desktop/src/main/modules/fileSearch/__tests__/macOS.integration.test.ts +357 -0
- package/apps/desktop/src/main/modules/fileSearch/impl/macOS.ts +30 -22
- package/changelog/v1.json +21 -0
- package/locales/ar/models.json +119 -126
- package/locales/ar/plugin.json +1 -1
- package/locales/bg-BG/models.json +104 -132
- package/locales/bg-BG/plugin.json +1 -1
- package/locales/de-DE/models.json +119 -126
- package/locales/de-DE/plugin.json +1 -1
- package/locales/en-US/models.json +167 -126
- package/locales/en-US/plugin.json +1 -1
- package/locales/es-ES/models.json +119 -126
- package/locales/es-ES/plugin.json +1 -1
- package/locales/fa-IR/models.json +119 -126
- package/locales/fa-IR/plugin.json +1 -1
- package/locales/fr-FR/models.json +119 -126
- package/locales/fr-FR/plugin.json +1 -1
- package/locales/it-IT/models.json +119 -126
- package/locales/it-IT/plugin.json +1 -1
- package/locales/ja-JP/models.json +119 -126
- package/locales/ja-JP/plugin.json +1 -1
- package/locales/ko-KR/models.json +119 -126
- package/locales/ko-KR/plugin.json +1 -1
- package/locales/nl-NL/models.json +119 -126
- package/locales/nl-NL/plugin.json +1 -1
- package/locales/pl-PL/models.json +119 -126
- package/locales/pl-PL/plugin.json +1 -1
- package/locales/pt-BR/models.json +119 -126
- package/locales/pt-BR/plugin.json +1 -1
- package/locales/ru-RU/models.json +119 -126
- package/locales/ru-RU/plugin.json +1 -1
- package/locales/tr-TR/models.json +119 -126
- package/locales/tr-TR/plugin.json +1 -1
- package/locales/vi-VN/models.json +119 -126
- package/locales/vi-VN/plugin.json +1 -1
- package/locales/zh-CN/models.json +173 -80
- package/locales/zh-CN/plugin.json +1 -1
- package/locales/zh-TW/models.json +119 -126
- package/locales/zh-TW/plugin.json +1 -1
- package/package.json +2 -2
- package/packages/const/src/models.ts +2 -0
- package/packages/electron-client-ipc/src/types/localSystem.ts +26 -2
- package/packages/electron-server-ipc/src/ipcClient.ts +31 -31
- package/packages/electron-server-ipc/src/ipcServer.ts +15 -15
- package/packages/model-bank/src/aiModels/aihubmix.ts +106 -2
- package/packages/model-bank/src/aiModels/openai.ts +107 -3
- package/packages/model-bank/src/aiModels/qwen.ts +76 -7
- package/packages/model-bank/src/types/aiModel.ts +1 -0
- package/packages/model-runtime/src/core/contextBuilders/openai.test.ts +58 -0
- package/packages/model-runtime/src/core/contextBuilders/openai.ts +24 -10
- package/packages/model-runtime/src/core/openaiCompatibleFactory/index.ts +3 -2
- package/packages/model-runtime/src/providers/openai/index.test.ts +44 -0
- package/packages/types/src/agent/chatConfig.ts +9 -0
- package/packages/types/src/tool/builtin.ts +6 -4
- package/src/app/[variants]/(main)/chat/components/WorkspaceLayout.tsx +32 -23
- package/src/features/ChatInput/ActionBar/Model/ControlsForm.tsx +12 -0
- package/src/features/ChatInput/ActionBar/Model/GPT51ReasoningEffortSlider.tsx +58 -0
- package/src/features/ChatItem/components/MessageContent.tsx +3 -1
- package/src/features/Conversation/Messages/Assistant/Tool/Render/LoadingPlaceholder/index.tsx +3 -3
- package/src/features/Conversation/Messages/Group/Tool/Render/Intervention/ApprovalActions.tsx +34 -13
- package/src/features/Conversation/Messages/Group/Tool/Render/Intervention/index.tsx +2 -2
- package/src/features/Conversation/Messages/Group/Tool/Render/LoadingPlaceholder/index.tsx +3 -3
- package/src/features/Conversation/Messages/User/index.tsx +11 -1
- package/src/features/PluginsUI/Render/BuiltinType/index.test.tsx +10 -4
- package/src/features/PluginsUI/Render/BuiltinType/index.tsx +2 -2
- package/src/libs/mcp/__tests__/__snapshots__/index.test.ts.snap +0 -6
- package/src/locales/default/chat.ts +2 -0
- package/src/locales/default/plugin.ts +1 -1
- package/src/services/chat/chat.test.ts +1 -0
- package/src/services/chat/index.ts +7 -0
- package/src/store/aiInfra/slices/aiProvider/__tests__/selectors.test.ts +62 -0
- package/src/store/aiInfra/slices/aiProvider/selectors.ts +1 -1
- package/src/store/chat/slices/aiChat/actions/conversationControl.ts +42 -0
- package/src/tools/code-interpreter/Render/index.tsx +1 -1
- package/src/tools/interventions.ts +28 -4
- package/src/tools/local-system/Intervention/RunCommand/index.tsx +4 -5
- package/src/tools/local-system/Placeholder/ListFiles.tsx +3 -5
- package/src/tools/local-system/Placeholder/SearchFiles.tsx +2 -5
- package/src/tools/local-system/Render/ListFiles/index.tsx +16 -21
- package/src/tools/local-system/Render/ReadLocalFile/ReadFileView.tsx +2 -1
- package/src/tools/local-system/Render/RenameLocalFile/index.tsx +15 -20
- package/src/tools/local-system/Render/RunCommand/index.tsx +67 -70
- package/src/tools/local-system/Render/SearchFiles/SearchQuery/index.tsx +0 -1
- package/src/tools/local-system/Render/SearchFiles/index.tsx +15 -20
- package/src/tools/local-system/Render/WriteFile/index.tsx +2 -8
- package/src/tools/local-system/index.ts +5 -4
- package/src/tools/local-system/systemRole.ts +1 -1
- package/src/tools/placeholders.ts +39 -8
- package/src/tools/renders.ts +56 -9
- package/src/tools/web-browsing/Placeholder/{PageContent.tsx → CrawlMultiPages.tsx} +4 -1
- package/src/tools/web-browsing/Placeholder/CrawlSinglePage.tsx +12 -0
- package/src/tools/web-browsing/Placeholder/Search.tsx +4 -4
- package/src/tools/web-browsing/Render/CrawlMultiPages.tsx +15 -0
- package/src/tools/web-browsing/Render/CrawlSinglePage.tsx +15 -0
- package/src/tools/web-browsing/Render/Search/index.tsx +39 -44
- package/packages/database/migrations/0044_add_tool_intervention.sql +0 -1
- package/src/tools/local-system/Intervention/index.tsx +0 -17
- package/src/tools/local-system/Placeholder/index.tsx +0 -25
- package/src/tools/local-system/Render/index.tsx +0 -42
- package/src/tools/web-browsing/Placeholder/index.tsx +0 -40
- package/src/tools/web-browsing/Render/index.tsx +0 -57
|
@@ -5,7 +5,7 @@ import { Flexbox } from 'react-layout-kit';
|
|
|
5
5
|
import { useChatStore } from '@/store/chat';
|
|
6
6
|
import { useUserStore } from '@/store/user';
|
|
7
7
|
import { toolInterventionSelectors } from '@/store/user/selectors';
|
|
8
|
-
import {
|
|
8
|
+
import { getBuiltinIntervention } from '@/tools/interventions';
|
|
9
9
|
|
|
10
10
|
import Arguments from '../Arguments';
|
|
11
11
|
import ApprovalActions from './ApprovalActions';
|
|
@@ -52,7 +52,7 @@ const Intervention = memo<InterventionProps>(
|
|
|
52
52
|
},
|
|
53
53
|
[requestArgs, id],
|
|
54
54
|
);
|
|
55
|
-
const BuiltinToolInterventionRender =
|
|
55
|
+
const BuiltinToolInterventionRender = getBuiltinIntervention(identifier, apiName);
|
|
56
56
|
|
|
57
57
|
if (BuiltinToolInterventionRender) {
|
|
58
58
|
if (isEditing)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { safeParseJSON } from '@lobechat/utils';
|
|
2
2
|
import { memo } from 'react';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { getBuiltinPlaceholder } from '@/tools/placeholders';
|
|
5
5
|
|
|
6
6
|
import Arguments from '../Arguments';
|
|
7
7
|
|
|
@@ -14,9 +14,9 @@ interface LoadingPlaceholderProps {
|
|
|
14
14
|
|
|
15
15
|
const LoadingPlaceholder = memo<LoadingPlaceholderProps>(
|
|
16
16
|
({ identifier, requestArgs, apiName, loading }) => {
|
|
17
|
-
const Render =
|
|
17
|
+
const Render = getBuiltinPlaceholder(identifier, apiName);
|
|
18
18
|
|
|
19
|
-
if (
|
|
19
|
+
if (Render) {
|
|
20
20
|
return (
|
|
21
21
|
<Render apiName={apiName} args={safeParseJSON(requestArgs) || {}} identifier={identifier} />
|
|
22
22
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { UIChatMessage } from '@lobechat/types';
|
|
2
2
|
import { Tag } from '@lobehub/ui';
|
|
3
|
-
import { useResponsive } from 'antd-style';
|
|
3
|
+
import { createStyles, useResponsive } from 'antd-style';
|
|
4
4
|
import isEqual from 'fast-deep-equal';
|
|
5
5
|
import { ReactNode, memo, useCallback, useMemo } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
@@ -45,6 +45,13 @@ const remarkPlugins = markdownElements
|
|
|
45
45
|
.map((element) => element.remarkPlugin)
|
|
46
46
|
.filter(Boolean);
|
|
47
47
|
|
|
48
|
+
const useUserStyles = createStyles(({ css, token }) => ({
|
|
49
|
+
messageContainer: css`
|
|
50
|
+
border: none;
|
|
51
|
+
background: ${token.colorFillTertiary};
|
|
52
|
+
`,
|
|
53
|
+
}));
|
|
54
|
+
|
|
48
55
|
const UserMessage = memo<UserMessageProps>(({ id, disableEditing, index }) => {
|
|
49
56
|
const item = useChatStore(
|
|
50
57
|
displayMessageSelectors.getDisplayMessageById(id),
|
|
@@ -56,6 +63,8 @@ const UserMessage = memo<UserMessageProps>(({ id, disableEditing, index }) => {
|
|
|
56
63
|
const { t } = useTranslation('chat');
|
|
57
64
|
const { mobile } = useResponsive();
|
|
58
65
|
const avatar = useUserAvatar();
|
|
66
|
+
const { styles: userStyles } = useUserStyles();
|
|
67
|
+
|
|
59
68
|
const title = useUserStore(userProfileSelectors.displayUserName);
|
|
60
69
|
|
|
61
70
|
const displayMode = useAgentStore(agentChatConfigSelectors.displayMode);
|
|
@@ -165,6 +174,7 @@ const UserMessage = memo<UserMessageProps>(({ id, disableEditing, index }) => {
|
|
|
165
174
|
>
|
|
166
175
|
<Flexbox flex={1} style={{ maxWidth: '100%', minWidth: 0 }}>
|
|
167
176
|
<MessageContent
|
|
177
|
+
className={userStyles.messageContainer}
|
|
168
178
|
editing={editing}
|
|
169
179
|
id={id}
|
|
170
180
|
markdownProps={markdownProps}
|
|
@@ -4,11 +4,17 @@ import { describe, expect, it, vi } from 'vitest';
|
|
|
4
4
|
import BuiltinType from './index';
|
|
5
5
|
|
|
6
6
|
// Mock renders module
|
|
7
|
+
const mockWebBrowsingRender = vi.fn(({ content }) => <div>WebBrowsingRender: {content}</div>);
|
|
8
|
+
const mockCodeInterpreterRender = vi.fn(({ content }) => (
|
|
9
|
+
<div>CodeInterpreterRender: {content}</div>
|
|
10
|
+
));
|
|
11
|
+
|
|
7
12
|
vi.mock('@/tools/renders', () => ({
|
|
8
|
-
|
|
9
|
-
'lobe-web-browsing'
|
|
10
|
-
'lobe-code-interpreter'
|
|
11
|
-
|
|
13
|
+
getBuiltinRender: vi.fn((identifier, apiName) => {
|
|
14
|
+
if (identifier === 'lobe-web-browsing') return mockWebBrowsingRender;
|
|
15
|
+
if (identifier === 'lobe-code-interpreter') return mockCodeInterpreterRender;
|
|
16
|
+
return undefined;
|
|
17
|
+
}),
|
|
12
18
|
}));
|
|
13
19
|
|
|
14
20
|
// Mock useParseContent hook
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { safeParseJSON } from '@lobechat/utils';
|
|
2
2
|
import { memo } from 'react';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { getBuiltinRender } from '@/tools/renders';
|
|
5
5
|
|
|
6
6
|
import { useParseContent } from '../useParseContent';
|
|
7
7
|
|
|
@@ -28,7 +28,7 @@ const BuiltinType = memo<BuiltinTypeProps>(
|
|
|
28
28
|
}) => {
|
|
29
29
|
const { data } = useParseContent(content);
|
|
30
30
|
|
|
31
|
-
const Render =
|
|
31
|
+
const Render = getBuiltinRender(identifier, apiName);
|
|
32
32
|
|
|
33
33
|
if (!Render) return;
|
|
34
34
|
|
|
@@ -5,8 +5,6 @@ exports[`MCPClient > Stdio Transport > should list tools via stdio 1`] = `
|
|
|
5
5
|
{
|
|
6
6
|
"description": "Echoes back a message with 'Hello' prefix",
|
|
7
7
|
"inputSchema": {
|
|
8
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
9
|
-
"additionalProperties": false,
|
|
10
8
|
"properties": {
|
|
11
9
|
"message": {
|
|
12
10
|
"description": "The message to echo",
|
|
@@ -23,8 +21,6 @@ exports[`MCPClient > Stdio Transport > should list tools via stdio 1`] = `
|
|
|
23
21
|
{
|
|
24
22
|
"description": "Lists all available tools and methods",
|
|
25
23
|
"inputSchema": {
|
|
26
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
27
|
-
"additionalProperties": false,
|
|
28
24
|
"properties": {},
|
|
29
25
|
"type": "object",
|
|
30
26
|
},
|
|
@@ -33,8 +29,6 @@ exports[`MCPClient > Stdio Transport > should list tools via stdio 1`] = `
|
|
|
33
29
|
{
|
|
34
30
|
"description": "Adds two numbers",
|
|
35
31
|
"inputSchema": {
|
|
36
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
37
|
-
"additionalProperties": false,
|
|
38
32
|
"properties": {
|
|
39
33
|
"a": {
|
|
40
34
|
"description": "The first number",
|
|
@@ -414,6 +414,8 @@ export default {
|
|
|
414
414
|
manualDesc: '每次调用都需要手动批准',
|
|
415
415
|
},
|
|
416
416
|
reject: '拒绝',
|
|
417
|
+
rejectAndContinue: '拒绝后重试执行',
|
|
418
|
+
rejectOnly: '拒绝',
|
|
417
419
|
rejectReasonPlaceholder: '输入拒绝原因将帮助 Agent 理解并优化后续行动',
|
|
418
420
|
rejectTitle: '拒绝本次工具调用',
|
|
419
421
|
rejectedWithReason: '本次工具调用被主动拒绝:{{reason}}',
|
|
@@ -174,6 +174,13 @@ class ChatService {
|
|
|
174
174
|
extendParams.reasoning_effort = chatConfig.gpt5ReasoningEffort;
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
if (
|
|
178
|
+
modelExtendParams!.includes('gpt5_1ReasoningEffort') &&
|
|
179
|
+
chatConfig.gpt5_1ReasoningEffort
|
|
180
|
+
) {
|
|
181
|
+
extendParams.reasoning_effort = chatConfig.gpt5_1ReasoningEffort;
|
|
182
|
+
}
|
|
183
|
+
|
|
177
184
|
if (modelExtendParams!.includes('textVerbosity') && chatConfig.textVerbosity) {
|
|
178
185
|
extendParams.verbosity = chatConfig.textVerbosity;
|
|
179
186
|
}
|
|
@@ -246,4 +246,66 @@ describe('aiProviderSelectors', () => {
|
|
|
246
246
|
);
|
|
247
247
|
});
|
|
248
248
|
});
|
|
249
|
+
|
|
250
|
+
describe('isProviderEnableResponseApi', () => {
|
|
251
|
+
it('should return true when config explicitly sets enableResponseApi to true', () => {
|
|
252
|
+
const state = {
|
|
253
|
+
...mockState,
|
|
254
|
+
aiProviderRuntimeConfig: {
|
|
255
|
+
test: {
|
|
256
|
+
config: { enableResponseApi: true },
|
|
257
|
+
keyVaults: {},
|
|
258
|
+
settings: {},
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
expect(aiProviderSelectors.isProviderEnableResponseApi('test')(state)).toBe(true);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('should return false when config explicitly sets enableResponseApi to false', () => {
|
|
266
|
+
const state = {
|
|
267
|
+
...mockState,
|
|
268
|
+
aiProviderRuntimeConfig: {
|
|
269
|
+
test: {
|
|
270
|
+
config: { enableResponseApi: false },
|
|
271
|
+
keyVaults: {},
|
|
272
|
+
settings: {},
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
expect(aiProviderSelectors.isProviderEnableResponseApi('test')(state)).toBe(false);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('should return true by default for openai provider', () => {
|
|
280
|
+
const state = {
|
|
281
|
+
...mockState,
|
|
282
|
+
aiProviderRuntimeConfig: {
|
|
283
|
+
openai: {
|
|
284
|
+
keyVaults: {},
|
|
285
|
+
settings: {},
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
expect(aiProviderSelectors.isProviderEnableResponseApi('openai')(state)).toBe(true);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('should return false by default for non-openai provider', () => {
|
|
293
|
+
const state = {
|
|
294
|
+
...mockState,
|
|
295
|
+
aiProviderRuntimeConfig: {
|
|
296
|
+
anthropic: {
|
|
297
|
+
keyVaults: {},
|
|
298
|
+
settings: {},
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
expect(aiProviderSelectors.isProviderEnableResponseApi('anthropic')(state)).toBe(false);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('should return false for provider without config', () => {
|
|
306
|
+
expect(aiProviderSelectors.isProviderEnableResponseApi('non-existing')(mockState)).toBe(
|
|
307
|
+
false,
|
|
308
|
+
);
|
|
309
|
+
});
|
|
310
|
+
});
|
|
249
311
|
});
|
|
@@ -108,7 +108,7 @@ const isProviderEnableResponseApi = (id: string) => (s: AIProviderStoreState) =>
|
|
|
108
108
|
|
|
109
109
|
if (typeof enableResponseApi === 'boolean') return enableResponseApi;
|
|
110
110
|
|
|
111
|
-
return
|
|
111
|
+
return id === 'openai';
|
|
112
112
|
};
|
|
113
113
|
|
|
114
114
|
const isInitAiProviderRuntimeState = (s: AIProviderStoreState) => !!s.isInitAiProviderRuntimeState;
|
|
@@ -43,6 +43,10 @@ export interface ConversationControlAction {
|
|
|
43
43
|
* Reject tool intervention
|
|
44
44
|
*/
|
|
45
45
|
rejectToolCalling: (messageId: string, reason?: string) => Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Reject tool intervention and continue
|
|
48
|
+
*/
|
|
49
|
+
rejectAndContinueToolCalling: (messageId: string, reason?: string) => Promise<void>;
|
|
46
50
|
/**
|
|
47
51
|
* Toggle sendMessage operation state
|
|
48
52
|
*/
|
|
@@ -206,6 +210,44 @@ export const conversationControl: StateCreator<
|
|
|
206
210
|
await get().optimisticUpdateMessageContent(messageId, toolContent);
|
|
207
211
|
},
|
|
208
212
|
|
|
213
|
+
rejectAndContinueToolCalling: async (messageId, reason) => {
|
|
214
|
+
await get().rejectToolCalling(messageId, reason);
|
|
215
|
+
|
|
216
|
+
const toolMessage = dbMessageSelectors.getDbMessageById(messageId)(get());
|
|
217
|
+
if (!toolMessage) return;
|
|
218
|
+
|
|
219
|
+
// Get current messages for state construction
|
|
220
|
+
const currentMessages = displayMessageSelectors.mainAIChats(get());
|
|
221
|
+
const { activeThreadId, internal_execAgentRuntime } = get();
|
|
222
|
+
|
|
223
|
+
// Create agent state and context to continue from rejected tool message
|
|
224
|
+
const { state, context: initialContext } = get().internal_createAgentState({
|
|
225
|
+
messages: currentMessages,
|
|
226
|
+
parentMessageId: messageId,
|
|
227
|
+
threadId: activeThreadId,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Override context with 'userInput' phase to continue as if user provided feedback
|
|
231
|
+
const context: AgentRuntimeContext = {
|
|
232
|
+
...initialContext,
|
|
233
|
+
phase: 'user_input',
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
// Execute agent runtime from rejected tool message position to continue
|
|
237
|
+
try {
|
|
238
|
+
await internal_execAgentRuntime({
|
|
239
|
+
messages: currentMessages,
|
|
240
|
+
parentMessageId: messageId,
|
|
241
|
+
parentMessageType: 'tool',
|
|
242
|
+
threadId: activeThreadId,
|
|
243
|
+
initialState: state,
|
|
244
|
+
initialContext: context,
|
|
245
|
+
});
|
|
246
|
+
} catch (error) {
|
|
247
|
+
console.error('[rejectAndContinueToolCalling] Error executing agent runtime:', error);
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
|
|
209
251
|
internal_updateSendMessageOperation: (key, value, actionName) => {
|
|
210
252
|
const operationKey = typeof key === 'string' ? key : messageMapKey(key.sessionId, key.topicId);
|
|
211
253
|
|
|
@@ -17,7 +17,7 @@ import { chatToolSelectors } from '@/store/chat/slices/builtinTool/selectors';
|
|
|
17
17
|
import ResultFileGallery from './components/ResultFileGallery';
|
|
18
18
|
|
|
19
19
|
const CodeInterpreter = memo<
|
|
20
|
-
BuiltinRenderProps<
|
|
20
|
+
BuiltinRenderProps<CodeInterpreterParams, CodeInterpreterState, CodeInterpreterResponse>
|
|
21
21
|
>(({ content, args, pluginState, messageId, apiName }) => {
|
|
22
22
|
const { t } = useTranslation('tool');
|
|
23
23
|
const theme = useTheme();
|
|
@@ -1,8 +1,32 @@
|
|
|
1
1
|
import { BuiltinIntervention } from '@lobechat/types';
|
|
2
2
|
|
|
3
|
-
import { LocalSystemManifest } from './local-system';
|
|
4
|
-
import
|
|
3
|
+
import { LocalSystemApiName, LocalSystemManifest } from './local-system';
|
|
4
|
+
import RunCommand from './local-system/Intervention/RunCommand';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Builtin tools interventions registry
|
|
8
|
+
* Organized by toolset (identifier) -> API name
|
|
9
|
+
* Only register APIs that have custom intervention UI
|
|
10
|
+
*/
|
|
11
|
+
export const BuiltinToolInterventions: Record<string, Record<string, any>> = {
|
|
12
|
+
[LocalSystemManifest.identifier]: {
|
|
13
|
+
[LocalSystemApiName.runCommand]: RunCommand,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get builtin intervention component for a specific API
|
|
19
|
+
* @param identifier - Tool identifier (e.g., 'lobe-local-system')
|
|
20
|
+
* @param apiName - API name (e.g., 'runCommand')
|
|
21
|
+
*/
|
|
22
|
+
export const getBuiltinIntervention = (
|
|
23
|
+
identifier?: string,
|
|
24
|
+
apiName?: string,
|
|
25
|
+
): BuiltinIntervention | undefined => {
|
|
26
|
+
if (!identifier || !apiName) return undefined;
|
|
27
|
+
|
|
28
|
+
const toolset = BuiltinToolInterventions[identifier];
|
|
29
|
+
if (!toolset) return undefined;
|
|
30
|
+
|
|
31
|
+
return toolset[apiName];
|
|
8
32
|
};
|
|
@@ -3,6 +3,8 @@ import { Highlighter, Text } from '@lobehub/ui';
|
|
|
3
3
|
import { memo } from 'react';
|
|
4
4
|
import { Flexbox } from 'react-layout-kit';
|
|
5
5
|
|
|
6
|
+
import { BuiltinInterventionProps } from '@/types/tool';
|
|
7
|
+
|
|
6
8
|
const formatTimeout = (ms?: number) => {
|
|
7
9
|
if (!ms) return null;
|
|
8
10
|
|
|
@@ -23,11 +25,8 @@ const formatTimeout = (ms?: number) => {
|
|
|
23
25
|
return `${ms}ms`;
|
|
24
26
|
};
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const RunCommand = memo<RunCommandProps>(({ description, command, timeout }) => {
|
|
28
|
+
const RunCommand = memo<BuiltinInterventionProps<RunCommandParams>>(({ args }) => {
|
|
29
|
+
const { description, command, timeout } = args;
|
|
31
30
|
return (
|
|
32
31
|
<Flexbox gap={8}>
|
|
33
32
|
<Flexbox horizontal justify={'space-between'}>
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { ListLocalFileParams } from '@lobechat/electron-client-ipc';
|
|
2
|
+
import { BuiltinPlaceholderProps } from '@lobechat/types';
|
|
2
3
|
import { Skeleton } from 'antd';
|
|
3
4
|
import React, { memo } from 'react';
|
|
4
5
|
import { Center, Flexbox } from 'react-layout-kit';
|
|
5
6
|
|
|
6
7
|
import { LocalFolder } from '@/features/LocalFile';
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
args: ListLocalFileParams;
|
|
10
|
-
}
|
|
11
|
-
export const ListFiles = memo<ListFilesProps>(({ args }) => {
|
|
9
|
+
export const ListFiles = memo<BuiltinPlaceholderProps<ListLocalFileParams>>(({ args }) => {
|
|
12
10
|
return (
|
|
13
11
|
<Flexbox gap={12}>
|
|
14
|
-
<LocalFolder path={args.path} />
|
|
12
|
+
{args?.path && <LocalFolder path={args.path} />}
|
|
15
13
|
<Center height={140}>
|
|
16
14
|
<Flexbox gap={4} width={'90%'}>
|
|
17
15
|
<Skeleton.Button active block style={{ height: 16 }} />
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LocalSearchFilesParams } from '@lobechat/electron-client-ipc';
|
|
2
|
+
import { BuiltinPlaceholderProps } from '@lobechat/types';
|
|
2
3
|
import { Icon } from '@lobehub/ui';
|
|
3
4
|
import { Skeleton } from 'antd';
|
|
4
5
|
import { createStyles } from 'antd-style';
|
|
@@ -21,11 +22,7 @@ const useStyles = createStyles(({ css, token, cx }) => ({
|
|
|
21
22
|
`),
|
|
22
23
|
}));
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
args: LocalSearchFilesParams;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const SearchFiles = memo<SearchFilesProps>(({ args }) => {
|
|
25
|
+
const SearchFiles = memo<BuiltinPlaceholderProps<LocalSearchFilesParams>>(({ args = {} }) => {
|
|
29
26
|
const { styles } = useStyles();
|
|
30
27
|
|
|
31
28
|
return (
|
|
@@ -1,31 +1,26 @@
|
|
|
1
1
|
import { ListLocalFileParams } from '@lobechat/electron-client-ipc';
|
|
2
|
-
import {
|
|
2
|
+
import { BuiltinRenderProps } from '@lobechat/types';
|
|
3
3
|
import React, { memo } from 'react';
|
|
4
4
|
|
|
5
5
|
import { LocalFolder } from '@/features/LocalFile';
|
|
6
|
-
import { LocalFileListState } from '@/tools/local-system/type';
|
|
7
6
|
|
|
7
|
+
import { LocalFileListState } from '../../type';
|
|
8
8
|
import SearchResult from './Result';
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
args
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
pluginError={pluginError}
|
|
25
|
-
/>
|
|
26
|
-
</>
|
|
27
|
-
);
|
|
28
|
-
});
|
|
10
|
+
const ListFiles = memo<BuiltinRenderProps<ListLocalFileParams, LocalFileListState>>(
|
|
11
|
+
({ messageId, pluginError, args, pluginState }) => {
|
|
12
|
+
return (
|
|
13
|
+
<>
|
|
14
|
+
<LocalFolder path={args.path} />
|
|
15
|
+
<SearchResult
|
|
16
|
+
listResults={pluginState?.listResults}
|
|
17
|
+
messageId={messageId}
|
|
18
|
+
pluginError={pluginError}
|
|
19
|
+
/>
|
|
20
|
+
</>
|
|
21
|
+
);
|
|
22
|
+
},
|
|
23
|
+
);
|
|
29
24
|
|
|
30
25
|
ListFiles.displayName = 'ListFiles';
|
|
31
26
|
|
|
@@ -26,9 +26,10 @@ const useStyles = createStyles(({ css, token, cx }) => ({
|
|
|
26
26
|
|
|
27
27
|
height: 64px;
|
|
28
28
|
padding: 8px;
|
|
29
|
-
border: 1px solid ${token.colorBorderSecondary};
|
|
30
29
|
border-radius: ${token.borderRadiusLG}px;
|
|
31
30
|
|
|
31
|
+
background: ${token.colorFillQuaternary};
|
|
32
|
+
|
|
32
33
|
transition: all 0.2s ${token.motionEaseInOut};
|
|
33
34
|
|
|
34
35
|
.local-file-actions {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RenameLocalFileParams } from '@lobechat/electron-client-ipc';
|
|
2
|
-
import {
|
|
2
|
+
import { BuiltinRenderProps } from '@lobechat/types';
|
|
3
3
|
import { Icon } from '@lobehub/ui';
|
|
4
4
|
import { createStyles } from 'antd-style';
|
|
5
5
|
import { ArrowRightIcon } from 'lucide-react';
|
|
@@ -19,27 +19,22 @@ const useStyles = createStyles(({ css, token }) => ({
|
|
|
19
19
|
`,
|
|
20
20
|
}));
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
args
|
|
24
|
-
|
|
25
|
-
pluginError: ChatMessagePluginError;
|
|
26
|
-
pluginState: LocalReadFileState;
|
|
27
|
-
}
|
|
22
|
+
const RenameLocalFile = memo<BuiltinRenderProps<RenameLocalFileParams, LocalReadFileState>>(
|
|
23
|
+
({ args }) => {
|
|
24
|
+
const { styles } = useStyles();
|
|
28
25
|
|
|
29
|
-
const
|
|
30
|
-
const { styles } = useStyles();
|
|
26
|
+
const { base: oldFileName, dir } = path.parse(args.path);
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
<
|
|
28
|
+
return (
|
|
29
|
+
<Flexbox align={'center'} className={styles.container} gap={8} horizontal paddingInline={12}>
|
|
30
|
+
<Flexbox>{oldFileName}</Flexbox>
|
|
31
|
+
<Flexbox>
|
|
32
|
+
<Icon icon={ArrowRightIcon} />
|
|
33
|
+
</Flexbox>
|
|
34
|
+
<LocalFile name={args.newName} path={path.join(dir, args.newName)} />
|
|
39
35
|
</Flexbox>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
});
|
|
36
|
+
);
|
|
37
|
+
},
|
|
38
|
+
);
|
|
44
39
|
|
|
45
40
|
export default RenameLocalFile;
|