@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.
Files changed (107) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +8 -8
  3. package/README.zh-CN.md +8 -8
  4. package/apps/desktop/package.json +1 -1
  5. package/apps/desktop/src/main/controllers/LocalFileCtr.ts +25 -5
  6. package/apps/desktop/src/main/controllers/__tests__/LocalFileCtr.test.ts +4 -1
  7. package/apps/desktop/src/main/modules/fileSearch/__tests__/macOS.integration.test.ts +357 -0
  8. package/apps/desktop/src/main/modules/fileSearch/impl/macOS.ts +30 -22
  9. package/changelog/v1.json +21 -0
  10. package/locales/ar/models.json +119 -126
  11. package/locales/ar/plugin.json +1 -1
  12. package/locales/bg-BG/models.json +104 -132
  13. package/locales/bg-BG/plugin.json +1 -1
  14. package/locales/de-DE/models.json +119 -126
  15. package/locales/de-DE/plugin.json +1 -1
  16. package/locales/en-US/models.json +167 -126
  17. package/locales/en-US/plugin.json +1 -1
  18. package/locales/es-ES/models.json +119 -126
  19. package/locales/es-ES/plugin.json +1 -1
  20. package/locales/fa-IR/models.json +119 -126
  21. package/locales/fa-IR/plugin.json +1 -1
  22. package/locales/fr-FR/models.json +119 -126
  23. package/locales/fr-FR/plugin.json +1 -1
  24. package/locales/it-IT/models.json +119 -126
  25. package/locales/it-IT/plugin.json +1 -1
  26. package/locales/ja-JP/models.json +119 -126
  27. package/locales/ja-JP/plugin.json +1 -1
  28. package/locales/ko-KR/models.json +119 -126
  29. package/locales/ko-KR/plugin.json +1 -1
  30. package/locales/nl-NL/models.json +119 -126
  31. package/locales/nl-NL/plugin.json +1 -1
  32. package/locales/pl-PL/models.json +119 -126
  33. package/locales/pl-PL/plugin.json +1 -1
  34. package/locales/pt-BR/models.json +119 -126
  35. package/locales/pt-BR/plugin.json +1 -1
  36. package/locales/ru-RU/models.json +119 -126
  37. package/locales/ru-RU/plugin.json +1 -1
  38. package/locales/tr-TR/models.json +119 -126
  39. package/locales/tr-TR/plugin.json +1 -1
  40. package/locales/vi-VN/models.json +119 -126
  41. package/locales/vi-VN/plugin.json +1 -1
  42. package/locales/zh-CN/models.json +173 -80
  43. package/locales/zh-CN/plugin.json +1 -1
  44. package/locales/zh-TW/models.json +119 -126
  45. package/locales/zh-TW/plugin.json +1 -1
  46. package/package.json +2 -2
  47. package/packages/const/src/models.ts +2 -0
  48. package/packages/electron-client-ipc/src/types/localSystem.ts +26 -2
  49. package/packages/electron-server-ipc/src/ipcClient.ts +31 -31
  50. package/packages/electron-server-ipc/src/ipcServer.ts +15 -15
  51. package/packages/model-bank/src/aiModels/aihubmix.ts +106 -2
  52. package/packages/model-bank/src/aiModels/openai.ts +107 -3
  53. package/packages/model-bank/src/aiModels/qwen.ts +76 -7
  54. package/packages/model-bank/src/types/aiModel.ts +1 -0
  55. package/packages/model-runtime/src/core/contextBuilders/openai.test.ts +58 -0
  56. package/packages/model-runtime/src/core/contextBuilders/openai.ts +24 -10
  57. package/packages/model-runtime/src/core/openaiCompatibleFactory/index.ts +3 -2
  58. package/packages/model-runtime/src/providers/openai/index.test.ts +44 -0
  59. package/packages/types/src/agent/chatConfig.ts +9 -0
  60. package/packages/types/src/tool/builtin.ts +6 -4
  61. package/src/app/[variants]/(main)/chat/components/WorkspaceLayout.tsx +32 -23
  62. package/src/features/ChatInput/ActionBar/Model/ControlsForm.tsx +12 -0
  63. package/src/features/ChatInput/ActionBar/Model/GPT51ReasoningEffortSlider.tsx +58 -0
  64. package/src/features/ChatItem/components/MessageContent.tsx +3 -1
  65. package/src/features/Conversation/Messages/Assistant/Tool/Render/LoadingPlaceholder/index.tsx +3 -3
  66. package/src/features/Conversation/Messages/Group/Tool/Render/Intervention/ApprovalActions.tsx +34 -13
  67. package/src/features/Conversation/Messages/Group/Tool/Render/Intervention/index.tsx +2 -2
  68. package/src/features/Conversation/Messages/Group/Tool/Render/LoadingPlaceholder/index.tsx +3 -3
  69. package/src/features/Conversation/Messages/User/index.tsx +11 -1
  70. package/src/features/PluginsUI/Render/BuiltinType/index.test.tsx +10 -4
  71. package/src/features/PluginsUI/Render/BuiltinType/index.tsx +2 -2
  72. package/src/libs/mcp/__tests__/__snapshots__/index.test.ts.snap +0 -6
  73. package/src/locales/default/chat.ts +2 -0
  74. package/src/locales/default/plugin.ts +1 -1
  75. package/src/services/chat/chat.test.ts +1 -0
  76. package/src/services/chat/index.ts +7 -0
  77. package/src/store/aiInfra/slices/aiProvider/__tests__/selectors.test.ts +62 -0
  78. package/src/store/aiInfra/slices/aiProvider/selectors.ts +1 -1
  79. package/src/store/chat/slices/aiChat/actions/conversationControl.ts +42 -0
  80. package/src/tools/code-interpreter/Render/index.tsx +1 -1
  81. package/src/tools/interventions.ts +28 -4
  82. package/src/tools/local-system/Intervention/RunCommand/index.tsx +4 -5
  83. package/src/tools/local-system/Placeholder/ListFiles.tsx +3 -5
  84. package/src/tools/local-system/Placeholder/SearchFiles.tsx +2 -5
  85. package/src/tools/local-system/Render/ListFiles/index.tsx +16 -21
  86. package/src/tools/local-system/Render/ReadLocalFile/ReadFileView.tsx +2 -1
  87. package/src/tools/local-system/Render/RenameLocalFile/index.tsx +15 -20
  88. package/src/tools/local-system/Render/RunCommand/index.tsx +67 -70
  89. package/src/tools/local-system/Render/SearchFiles/SearchQuery/index.tsx +0 -1
  90. package/src/tools/local-system/Render/SearchFiles/index.tsx +15 -20
  91. package/src/tools/local-system/Render/WriteFile/index.tsx +2 -8
  92. package/src/tools/local-system/index.ts +5 -4
  93. package/src/tools/local-system/systemRole.ts +1 -1
  94. package/src/tools/placeholders.ts +39 -8
  95. package/src/tools/renders.ts +56 -9
  96. package/src/tools/web-browsing/Placeholder/{PageContent.tsx → CrawlMultiPages.tsx} +4 -1
  97. package/src/tools/web-browsing/Placeholder/CrawlSinglePage.tsx +12 -0
  98. package/src/tools/web-browsing/Placeholder/Search.tsx +4 -4
  99. package/src/tools/web-browsing/Render/CrawlMultiPages.tsx +15 -0
  100. package/src/tools/web-browsing/Render/CrawlSinglePage.tsx +15 -0
  101. package/src/tools/web-browsing/Render/Search/index.tsx +39 -44
  102. package/packages/database/migrations/0044_add_tool_intervention.sql +0 -1
  103. package/src/tools/local-system/Intervention/index.tsx +0 -17
  104. package/src/tools/local-system/Placeholder/index.tsx +0 -25
  105. package/src/tools/local-system/Render/index.tsx +0 -42
  106. package/src/tools/web-browsing/Placeholder/index.tsx +0 -40
  107. package/src/tools/web-browsing/Render/index.tsx +0 -57
@@ -1,6 +1,6 @@
1
1
  import { CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons';
2
2
  import { RunCommandParams, RunCommandResult } from '@lobechat/electron-client-ipc';
3
- import { ChatMessagePluginError } from '@lobechat/types';
3
+ import { BuiltinRenderProps } from '@lobechat/types';
4
4
  import { ActionIcon, Block, Highlighter, Text } from '@lobehub/ui';
5
5
  import { createStyles } from 'antd-style';
6
6
  import { ChevronDown, ChevronUp } from 'lucide-react';
@@ -33,82 +33,79 @@ const useStyles = createStyles(({ css, token }) => ({
33
33
  `,
34
34
  }));
35
35
 
36
- interface RunCommandProps {
37
- args: RunCommandParams;
38
- messageId: string;
39
- pluginError: ChatMessagePluginError;
40
- pluginState: {
41
- message: string;
42
- result: RunCommandResult;
43
- };
36
+ interface RunCommandState {
37
+ message: string;
38
+ result: RunCommandResult;
44
39
  }
45
40
 
46
- const RunCommand = memo<RunCommandProps>(({ args, pluginState }) => {
47
- const { styles, theme } = useStyles();
48
- const { result, message } = pluginState || {};
49
- const isSuccess = result?.success;
50
- const [expanded, setExpanded] = useState(false);
41
+ const RunCommand = memo<BuiltinRenderProps<RunCommandParams, RunCommandState>>(
42
+ ({ args, pluginState }) => {
43
+ const { styles, theme } = useStyles();
44
+ const { result, message } = pluginState || {};
45
+ const isSuccess = result?.success;
46
+ const [expanded, setExpanded] = useState(false);
51
47
 
52
- return (
53
- <Flexbox className={styles.container} gap={8}>
54
- {/* Header: Description + Status */}
55
- <Flexbox align={'center'} className={styles.header} horizontal justify={'space-between'}>
56
- <Flexbox gap={8} horizontal>
57
- <Flexbox gap={4} horizontal>
58
- {!result ? null : isSuccess ? (
59
- <CheckCircleFilled
60
- className={styles.statusIcon}
61
- style={{ color: theme.colorSuccess }}
62
- />
63
- ) : (
64
- <CloseCircleFilled
65
- className={styles.statusIcon}
66
- style={{ color: theme.colorError }}
67
- />
48
+ return (
49
+ <Flexbox className={styles.container} gap={8}>
50
+ {/* Header: Description + Status */}
51
+ <Flexbox align={'center'} className={styles.header} horizontal justify={'space-between'}>
52
+ <Flexbox gap={8} horizontal>
53
+ <Flexbox gap={4} horizontal>
54
+ {!result ? null : isSuccess ? (
55
+ <CheckCircleFilled
56
+ className={styles.statusIcon}
57
+ style={{ color: theme.colorSuccess }}
58
+ />
59
+ ) : (
60
+ <CloseCircleFilled
61
+ className={styles.statusIcon}
62
+ style={{ color: theme.colorError }}
63
+ />
64
+ )}
65
+ {args.description && <Text className={styles.head}>{args.description}</Text>}
66
+ </Flexbox>
67
+ {message && (
68
+ <Flexbox align={'center'} gap={4} horizontal>
69
+ <Text className={styles.head} type={'secondary'}>
70
+ {message}
71
+ </Text>
72
+ </Flexbox>
68
73
  )}
69
- {args.description && <Text className={styles.head}>{args.description}</Text>}
70
74
  </Flexbox>
71
- {message && (
72
- <Flexbox align={'center'} gap={4} horizontal>
73
- <Text className={styles.head} type={'secondary'}>
74
- {message}
75
- </Text>
76
- </Flexbox>
77
- )}
78
- </Flexbox>
79
- <Flexbox align={'center'} gap={8} horizontal>
80
- <ActionIcon
81
- className={`action-icon`}
82
- icon={expanded ? ChevronUp : ChevronDown}
83
- onClick={() => setExpanded(!expanded)}
84
- size={'small'}
85
- style={{ opacity: expanded ? 1 : undefined }}
86
- title={expanded ? 'Collapse' : 'Expand'}
87
- />
75
+ <Flexbox align={'center'} gap={8} horizontal>
76
+ <ActionIcon
77
+ className={`action-icon`}
78
+ icon={expanded ? ChevronUp : ChevronDown}
79
+ onClick={() => setExpanded(!expanded)}
80
+ size={'small'}
81
+ style={{ opacity: expanded ? 1 : undefined }}
82
+ title={expanded ? 'Collapse' : 'Expand'}
83
+ />
84
+ </Flexbox>
88
85
  </Flexbox>
89
- </Flexbox>
90
86
 
91
- {/* Command & Output */}
92
- {expanded && (
93
- <Block gap={8} padding={8} variant={'outlined'}>
94
- <Highlighter
95
- language={'sh'}
96
- showLanguage={false}
97
- style={{ paddingInline: 8 }}
98
- variant={'borderless'}
99
- wrap
100
- >
101
- {args.command}
102
- </Highlighter>
103
- {result?.output && (
104
- <Highlighter language={'text'} showLanguage={false} variant={'filled'} wrap>
105
- {result.output}
87
+ {/* Command & Output */}
88
+ {expanded && (
89
+ <Block gap={8} padding={8} variant={'outlined'}>
90
+ <Highlighter
91
+ language={'sh'}
92
+ showLanguage={false}
93
+ style={{ paddingInline: 8 }}
94
+ variant={'borderless'}
95
+ wrap
96
+ >
97
+ {args.command}
106
98
  </Highlighter>
107
- )}
108
- </Block>
109
- )}
110
- </Flexbox>
111
- );
112
- });
99
+ {result?.output && (
100
+ <Highlighter language={'text'} showLanguage={false} variant={'filled'} wrap>
101
+ {result.output}
102
+ </Highlighter>
103
+ )}
104
+ </Block>
105
+ )}
106
+ </Flexbox>
107
+ );
108
+ },
109
+ );
113
110
 
114
111
  export default RunCommand;
@@ -13,7 +13,6 @@ import SearchView from './SearchView';
13
13
 
14
14
  interface SearchQueryViewProps {
15
15
  args: LocalSearchFilesParams;
16
-
17
16
  messageId: string;
18
17
  pluginState?: LocalFileSearchState;
19
18
  }
@@ -1,5 +1,5 @@
1
1
  import { LocalSearchFilesParams } from '@lobechat/electron-client-ipc';
2
- import { ChatMessagePluginError } from '@lobechat/types';
2
+ import { BuiltinRenderProps } from '@lobechat/types';
3
3
  import { memo } from 'react';
4
4
  import { Flexbox } from 'react-layout-kit';
5
5
 
@@ -8,25 +8,20 @@ import { LocalFileSearchState } from '@/tools/local-system/type';
8
8
  import SearchResult from './Result';
9
9
  import SearchQuery from './SearchQuery';
10
10
 
11
- interface SearchFilesProps {
12
- args: LocalSearchFilesParams;
13
- messageId: string;
14
- pluginError: ChatMessagePluginError;
15
- pluginState?: LocalFileSearchState;
16
- }
17
-
18
- const SearchFiles = memo<SearchFilesProps>(({ messageId, pluginError, args, pluginState }) => {
19
- return (
20
- <Flexbox gap={4}>
21
- <SearchQuery args={args} messageId={messageId} pluginState={pluginState} />
22
- <SearchResult
23
- messageId={messageId}
24
- pluginError={pluginError}
25
- searchResults={pluginState?.searchResults}
26
- />
27
- </Flexbox>
28
- );
29
- });
11
+ const SearchFiles = memo<BuiltinRenderProps<LocalSearchFilesParams, LocalFileSearchState>>(
12
+ ({ messageId, pluginError, args, pluginState }) => {
13
+ return (
14
+ <Flexbox gap={4}>
15
+ <SearchQuery args={args} messageId={messageId} pluginState={pluginState} />
16
+ <SearchResult
17
+ messageId={messageId}
18
+ pluginError={pluginError}
19
+ searchResults={pluginState?.searchResults}
20
+ />
21
+ </Flexbox>
22
+ );
23
+ },
24
+ );
30
25
 
31
26
  SearchFiles.displayName = 'SearchFiles';
32
27
 
@@ -1,5 +1,5 @@
1
1
  import { WriteLocalFileParams } from '@lobechat/electron-client-ipc';
2
- import { ChatMessagePluginError } from '@lobechat/types';
2
+ import { BuiltinRenderProps } from '@lobechat/types';
3
3
  import { Icon } from '@lobehub/ui';
4
4
  import { Skeleton } from 'antd';
5
5
  import { ChevronRight } from 'lucide-react';
@@ -9,13 +9,7 @@ import { Flexbox } from 'react-layout-kit';
9
9
 
10
10
  import { LocalFile, LocalFolder } from '@/features/LocalFile';
11
11
 
12
- interface WriteFileProps {
13
- args: WriteLocalFileParams;
14
- messageId: string;
15
- pluginError: ChatMessagePluginError;
16
- }
17
-
18
- const WriteFile = memo<WriteFileProps>(({ args }) => {
12
+ const WriteFile = memo<BuiltinRenderProps<WriteLocalFileParams>>(({ args }) => {
19
13
  if (!args) return <Skeleton active />;
20
14
 
21
15
  const { base, dir } = path.parse(args.path);
@@ -78,6 +78,10 @@ export const LocalSystemManifest: BuiltinToolManifest = {
78
78
  format: 'date-time',
79
79
  type: 'string',
80
80
  },
81
+ directory: {
82
+ description: 'Limit the search to this specific directory path',
83
+ type: 'string',
84
+ },
81
85
  exclude: {
82
86
  description: 'Array of file or directory paths to exclude',
83
87
  items: {
@@ -114,10 +118,6 @@ export const LocalSystemManifest: BuiltinToolManifest = {
114
118
  format: 'date-time',
115
119
  type: 'string',
116
120
  },
117
- onlyIn: {
118
- description: 'Limit the search to this specific directory path',
119
- type: 'string',
120
- },
121
121
  sortBy: {
122
122
  description: 'Sort results by',
123
123
  enum: ['name', 'date', 'size'],
@@ -186,6 +186,7 @@ export const LocalSystemManifest: BuiltinToolManifest = {
186
186
  {
187
187
  description:
188
188
  'Write content to a specific file. Input should be the file path and content. Overwrites existing file or creates a new one.',
189
+ humanIntervention: 'required',
189
190
  name: LocalSystemApiName.writeLocalFile,
190
191
  parameters: {
191
192
  properties: {
@@ -1,4 +1,4 @@
1
- export const systemPrompt = `You have a Local System tool with capabilities to interact with the user's local file system. You can list directories, read file contents, search for files, move, and rename files/directories.
1
+ export const systemPrompt = `You have a Local System tool with capabilities to interact with the user's local system. You can list directories, read file contents, search for files, move, and rename files/directories.
2
2
 
3
3
  <user_context>
4
4
  Here are some known locations and system details on the user's system. User is using the Operating System: {{platform}}({{arch}}). Use these paths when the user refers to these common locations by name (e.g., "my desktop", "downloads folder").
@@ -1,11 +1,42 @@
1
1
  import { BuiltinPlaceholder } from '@lobechat/types';
2
2
 
3
- import { LocalSystemManifest } from './local-system';
4
- import LocalSystem from './local-system/Placeholder';
5
- import { WebBrowsingManifest } from './web-browsing';
6
- import WebBrowsing from './web-browsing/Placeholder';
7
-
8
- export const BuiltinToolPlaceholders: Record<string, BuiltinPlaceholder> = {
9
- [WebBrowsingManifest.identifier]: WebBrowsing as BuiltinPlaceholder,
10
- [LocalSystemManifest.identifier]: LocalSystem as BuiltinPlaceholder,
3
+ import { LocalSystemApiName, LocalSystemManifest } from './local-system';
4
+ import { ListFiles as LocalSystemListFiles } from './local-system/Placeholder/ListFiles';
5
+ import LocalSystemSearchFiles from './local-system/Placeholder/SearchFiles';
6
+ import { WebBrowsingApiName, WebBrowsingManifest } from './web-browsing';
7
+ import CrawlMultiPages from './web-browsing/Placeholder/CrawlMultiPages';
8
+ import CrawlSinglePage from './web-browsing/Placeholder/CrawlSinglePage';
9
+ import { Search } from './web-browsing/Placeholder/Search';
10
+
11
+ /**
12
+ * Builtin tools placeholders registry
13
+ * Organized by toolset (identifier) -> API name
14
+ */
15
+ export const BuiltinToolPlaceholders: Record<string, Record<string, any>> = {
16
+ [LocalSystemManifest.identifier]: {
17
+ [LocalSystemApiName.searchLocalFiles]: LocalSystemSearchFiles,
18
+ [LocalSystemApiName.listLocalFiles]: LocalSystemListFiles,
19
+ },
20
+ [WebBrowsingManifest.identifier]: {
21
+ [WebBrowsingApiName.search]: Search,
22
+ [WebBrowsingApiName.crawlSinglePage]: CrawlSinglePage,
23
+ [WebBrowsingApiName.crawlMultiPages]: CrawlMultiPages,
24
+ },
25
+ };
26
+
27
+ /**
28
+ * Get builtin placeholder component for a specific API
29
+ * @param identifier - Tool identifier (e.g., 'lobe-local-system')
30
+ * @param apiName - API name (e.g., 'searchLocalFiles')
31
+ */
32
+ export const getBuiltinPlaceholder = (
33
+ identifier?: string,
34
+ apiName?: string,
35
+ ): BuiltinPlaceholder | undefined => {
36
+ if (!identifier || !apiName) return undefined;
37
+
38
+ const toolset = BuiltinToolPlaceholders[identifier];
39
+ if (!toolset) return undefined;
40
+
41
+ return toolset[apiName];
11
42
  };
@@ -2,13 +2,60 @@ import { BuiltinRender } from '@lobechat/types';
2
2
 
3
3
  import { CodeInterpreterManifest } from './code-interpreter';
4
4
  import CodeInterpreterRender from './code-interpreter/Render';
5
- import { LocalSystemManifest } from './local-system';
6
- import LocalFilesRender from './local-system/Render';
7
- import { WebBrowsingManifest } from './web-browsing';
8
- import WebBrowsing from './web-browsing/Render';
9
-
10
- export const BuiltinToolsRenders: Record<string, BuiltinRender> = {
11
- [WebBrowsingManifest.identifier]: WebBrowsing as BuiltinRender,
12
- [LocalSystemManifest.identifier]: LocalFilesRender as BuiltinRender,
13
- [CodeInterpreterManifest.identifier]: CodeInterpreterRender as BuiltinRender,
5
+ // local-system
6
+ import { LocalSystemApiName, LocalSystemManifest } from './local-system';
7
+ import ListFiles from './local-system/Render/ListFiles';
8
+ import ReadLocalFile from './local-system/Render/ReadLocalFile';
9
+ import RenameLocalFile from './local-system/Render/RenameLocalFile';
10
+ import RunCommand from './local-system/Render/RunCommand';
11
+ import SearchFiles from './local-system/Render/SearchFiles';
12
+ import WriteFile from './local-system/Render/WriteFile';
13
+ // web-browsing
14
+ import { WebBrowsingApiName, WebBrowsingManifest } from './web-browsing';
15
+ import CrawlMultiPages from './web-browsing/Render/CrawlMultiPages';
16
+ import CrawlSinglePage from './web-browsing/Render/CrawlSinglePage';
17
+ import Search from './web-browsing/Render/Search';
18
+
19
+ /**
20
+ * Builtin tools renders registry
21
+ * Organized by toolset (identifier) -> API name
22
+ */
23
+ const BuiltinToolsRenders: Record<string, Record<string, BuiltinRender>> = {
24
+ [LocalSystemManifest.identifier]: {
25
+ [LocalSystemApiName.searchLocalFiles]: SearchFiles as BuiltinRender,
26
+ [LocalSystemApiName.listLocalFiles]: ListFiles as BuiltinRender,
27
+ [LocalSystemApiName.readLocalFile]: ReadLocalFile as BuiltinRender,
28
+ [LocalSystemApiName.renameLocalFile]: RenameLocalFile as BuiltinRender,
29
+ [LocalSystemApiName.writeLocalFile]: WriteFile as BuiltinRender,
30
+ [LocalSystemApiName.runCommand]: RunCommand as BuiltinRender,
31
+ },
32
+ [WebBrowsingManifest.identifier]: {
33
+ [WebBrowsingApiName.search]: Search as BuiltinRender,
34
+ [WebBrowsingApiName.crawlSinglePage]: CrawlSinglePage as BuiltinRender,
35
+ [WebBrowsingApiName.crawlMultiPages]: CrawlMultiPages as BuiltinRender,
36
+ },
37
+ [CodeInterpreterManifest.identifier]: {
38
+ python: CodeInterpreterRender as BuiltinRender,
39
+ },
40
+ };
41
+
42
+ /**
43
+ * Get builtin render component for a specific API
44
+ * @param identifier - Tool identifier (e.g., 'lobe-local-system')
45
+ * @param apiName - API name (e.g., 'searchLocalFiles')
46
+ */
47
+ export const getBuiltinRender = (
48
+ identifier?: string,
49
+ apiName?: string,
50
+ ): BuiltinRender | undefined => {
51
+ if (!identifier) return undefined;
52
+
53
+ const toolset = BuiltinToolsRenders[identifier];
54
+ if (!toolset) return undefined;
55
+
56
+ if (apiName && toolset[apiName]) {
57
+ return toolset[apiName];
58
+ }
59
+
60
+ return undefined;
14
61
  };
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { BuiltinPlaceholderProps } from '@lobechat/types';
3
4
  import { ScrollShadow } from '@lobehub/ui';
4
5
  import { memo } from 'react';
5
6
 
@@ -7,7 +8,9 @@ import { useIsMobile } from '@/hooks/useIsMobile';
7
8
 
8
9
  import LoadingCard from '../Render/PageContent/Loading';
9
10
 
10
- const PageContent = memo<{ urls: string[] }>(({ urls }) => {
11
+ const PageContent = memo<BuiltinPlaceholderProps<{ urls: string[] }>>(({ args }) => {
12
+ const urls = args?.urls;
13
+
11
14
  const isMobile = useIsMobile();
12
15
 
13
16
  return (
@@ -0,0 +1,12 @@
1
+ 'use client';
2
+
3
+ import { BuiltinPlaceholderProps } from '@lobechat/types';
4
+ import { memo } from 'react';
5
+
6
+ import LoadingCard from '../Render/PageContent/Loading';
7
+
8
+ const CrawlSinglePage = memo<BuiltinPlaceholderProps<{ url: string }>>(({ args }) => {
9
+ return <LoadingCard url={args?.url || ''} />;
10
+ });
11
+
12
+ export default CrawlSinglePage;
@@ -1,3 +1,4 @@
1
+ import { BuiltinPlaceholderProps, SearchQuery } from '@lobechat/types';
1
2
  import { Icon } from '@lobehub/ui';
2
3
  import { Skeleton } from 'antd';
3
4
  import { createStyles } from 'antd-style';
@@ -29,10 +30,9 @@ const useStyles = createStyles(({ css, token, cx }) => ({
29
30
  ),
30
31
  }));
31
32
 
32
- interface SearchProps {
33
- query?: string;
34
- }
35
- export const Search = memo<SearchProps>(({ query }) => {
33
+ export const Search = memo<BuiltinPlaceholderProps<SearchQuery>>(({ args }) => {
34
+ const { query } = args || {};
35
+
36
36
  const isMobile = useIsMobile();
37
37
  const { styles } = useStyles();
38
38
  return (
@@ -0,0 +1,15 @@
1
+ import { BuiltinRenderProps, CrawlMultiPagesQuery, CrawlPluginState } from '@lobechat/types';
2
+ import { memo } from 'react';
3
+
4
+ import PageContent from './PageContent';
5
+
6
+ const CrawlSinglePage = memo<BuiltinRenderProps<CrawlMultiPagesQuery, CrawlPluginState>>(
7
+ ({ messageId, pluginState = {}, args = {} }) => {
8
+ const { results } = pluginState;
9
+ const { urls } = args;
10
+
11
+ return <PageContent messageId={messageId} results={results} urls={urls} />;
12
+ },
13
+ );
14
+
15
+ export default CrawlSinglePage;
@@ -0,0 +1,15 @@
1
+ import { BuiltinRenderProps, CrawlPluginState, CrawlSinglePageQuery } from '@lobechat/types';
2
+ import { memo } from 'react';
3
+
4
+ import PageContent from './PageContent';
5
+
6
+ const MultiPages = memo<BuiltinRenderProps<CrawlSinglePageQuery, CrawlPluginState>>(
7
+ ({ messageId, pluginState, args }) => {
8
+ const { results } = pluginState || {};
9
+ const { url } = args || {};
10
+
11
+ return <PageContent messageId={messageId} results={results} urls={[url]} />;
12
+ },
13
+ );
14
+
15
+ export default MultiPages;
@@ -1,4 +1,4 @@
1
- import { ChatMessagePluginError, SearchQuery, UniformSearchResponse } from '@lobechat/types';
1
+ import { BuiltinRenderProps, SearchQuery, UniformSearchResponse } from '@lobechat/types';
2
2
  import { Alert, Highlighter } from '@lobehub/ui';
3
3
  import { memo, useState } from 'react';
4
4
  import { Flexbox } from 'react-layout-kit';
@@ -7,54 +7,49 @@ import ConfigForm from './ConfigForm';
7
7
  import SearchQueryView from './SearchQuery';
8
8
  import SearchResult from './SearchResult';
9
9
 
10
- interface SearchProps {
11
- messageId: string;
12
- pluginError: ChatMessagePluginError;
13
- searchQuery: SearchQuery;
14
- searchResponse?: UniformSearchResponse;
15
- }
10
+ const Search = memo<BuiltinRenderProps<SearchQuery, UniformSearchResponse>>(
11
+ ({ messageId, args: searchQuery, pluginState: searchResponse, pluginError }) => {
12
+ const [editing, setEditing] = useState(false);
16
13
 
17
- const Search = memo<SearchProps>(({ messageId, searchQuery, searchResponse, pluginError }) => {
18
- const [editing, setEditing] = useState(false);
14
+ if (pluginError) {
15
+ if (pluginError?.type === 'PluginSettingsInvalid') {
16
+ return <ConfigForm id={messageId} provider={pluginError.body?.provider} />;
17
+ }
19
18
 
20
- if (pluginError) {
21
- if (pluginError?.type === 'PluginSettingsInvalid') {
22
- return <ConfigForm id={messageId} provider={pluginError.body?.provider} />;
19
+ return (
20
+ <Alert
21
+ extra={
22
+ <Flexbox>
23
+ <Highlighter actionIconSize={'small'} language={'json'} variant={'borderless'}>
24
+ {JSON.stringify(pluginError.body?.data || pluginError.body, null, 2)}
25
+ </Highlighter>
26
+ </Flexbox>
27
+ }
28
+ message={pluginError?.message}
29
+ type={'error'}
30
+ />
31
+ );
23
32
  }
24
33
 
25
34
  return (
26
- <Alert
27
- extra={
28
- <Flexbox>
29
- <Highlighter actionIconSize={'small'} language={'json'} variant={'borderless'}>
30
- {JSON.stringify(pluginError.body?.data || pluginError.body, null, 2)}
31
- </Highlighter>
32
- </Flexbox>
33
- }
34
- message={pluginError?.message}
35
- type={'error'}
36
- />
35
+ <Flexbox gap={8}>
36
+ <SearchQueryView
37
+ args={searchQuery}
38
+ editing={editing}
39
+ messageId={messageId}
40
+ pluginState={searchResponse}
41
+ setEditing={setEditing}
42
+ />
43
+ <SearchResult
44
+ args={searchQuery}
45
+ editing={editing}
46
+ messageId={messageId}
47
+ pluginState={searchResponse}
48
+ setEditing={setEditing}
49
+ />
50
+ </Flexbox>
37
51
  );
38
- }
39
-
40
- return (
41
- <Flexbox gap={8}>
42
- <SearchQueryView
43
- args={searchQuery}
44
- editing={editing}
45
- messageId={messageId}
46
- pluginState={searchResponse}
47
- setEditing={setEditing}
48
- />
49
- <SearchResult
50
- args={searchQuery}
51
- editing={editing}
52
- messageId={messageId}
53
- pluginState={searchResponse}
54
- setEditing={setEditing}
55
- />
56
- </Flexbox>
57
- );
58
- });
52
+ },
53
+ );
59
54
 
60
55
  export default Search;
@@ -1 +0,0 @@
1
- ALTER TABLE "message_plugins" ADD COLUMN "intervention" jsonb;
@@ -1,17 +0,0 @@
1
- import { RunCommandParams } from '@lobechat/electron-client-ipc';
2
- import { BuiltinInterventionProps } from '@lobechat/types';
3
- import { memo } from 'react';
4
-
5
- import RunCommand from './RunCommand';
6
-
7
- const Intervention = memo<BuiltinInterventionProps<RunCommandParams>>(
8
- ({ apiName, args, messageId }) => {
9
- if (apiName === 'runCommand') {
10
- return <RunCommand {...args} messageId={messageId} />;
11
- }
12
-
13
- return null;
14
- },
15
- );
16
-
17
- export default Intervention;
@@ -1,25 +0,0 @@
1
- import { BuiltinPlaceholderProps } from '@lobechat/types';
2
- import { memo } from 'react';
3
-
4
- import { LocalSystemApiName } from '@/tools/local-system';
5
-
6
- import ReadLocalFile from '../Render/ReadLocalFile/ReadFileSkeleton';
7
- import { ListFiles } from './ListFiles';
8
- import SearchFiles from './SearchFiles';
9
-
10
- const RenderMap = {
11
- [LocalSystemApiName.searchLocalFiles]: SearchFiles,
12
- [LocalSystemApiName.listLocalFiles]: ListFiles,
13
- [LocalSystemApiName.readLocalFile]: ReadLocalFile,
14
- // [LocalSystemApiName.renameLocalFile]: RenameLocalFile,
15
- // [LocalSystemApiName.writeLocalFile]: WriteFile,
16
- };
17
- const Placeholder = memo<BuiltinPlaceholderProps>(({ apiName, args }) => {
18
- const Render = RenderMap[apiName as any];
19
-
20
- if (!Render) return;
21
-
22
- return <Render args={(args || {}) as any} />;
23
- });
24
-
25
- export default Placeholder;