@lobehub/lobehub 2.0.0-next.53 → 2.0.0-next.54

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 CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 2.0.0-next.54](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.53...v2.0.0-next.54)
6
+
7
+ <sup>Released on **2025-11-14**</sup>
8
+
9
+ #### 💄 Styles
10
+
11
+ - **misc**: Refactor and support move locale file intervention.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Styles
19
+
20
+ - **misc**: Refactor and support move locale file intervention, closes [#10213](https://github.com/lobehub/lobe-chat/issues/10213) ([63cac81](https://github.com/lobehub/lobe-chat/commit/63cac81))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ## [Version 2.0.0-next.53](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.52...v2.0.0-next.53)
6
31
 
7
32
  <sup>Released on **2025-11-14**</sup>
package/changelog/v1.json CHANGED
@@ -1,4 +1,13 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "improvements": [
5
+ "Refactor and support move locale file intervention."
6
+ ]
7
+ },
8
+ "date": "2025-11-14",
9
+ "version": "2.0.0-next.54"
10
+ },
2
11
  {
3
12
  "children": {
4
13
  "features": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/lobehub",
3
- "version": "2.0.0-next.53",
3
+ "version": "2.0.0-next.54",
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",
@@ -3,7 +3,7 @@
3
3
  import { LOADING_FLAT } from '@lobechat/const';
4
4
  import { UIChatMessage } from '@lobechat/types';
5
5
  import { Tag } from '@lobehub/ui';
6
- import { useResponsive } from 'antd-style';
6
+ import { css, cx, useResponsive } from 'antd-style';
7
7
  import isEqual from 'fast-deep-equal';
8
8
  import { ReactNode, memo, useCallback, useMemo } from 'react';
9
9
  import { useTranslation } from 'react-i18next';
@@ -39,6 +39,11 @@ import { AssistantMessageContent } from './MessageContent';
39
39
  const rehypePlugins = markdownElements.map((element) => element.rehypePlugin).filter(Boolean);
40
40
  const remarkPlugins = markdownElements.map((element) => element.remarkPlugin).filter(Boolean);
41
41
 
42
+ const messageContainer = cx(css`
43
+ border: none;
44
+ background: none;
45
+ `);
46
+
42
47
  const isHtmlCode = (content: string, language: string) => {
43
48
  return (
44
49
  language === 'html' ||
@@ -248,6 +253,7 @@ const AssistantMessage = memo<AssistantMessageProps>(({ id, index, disableEditin
248
253
  <ErrorContent error={errorContent} message={errorMessage} placement={placement} />
249
254
  ) : (
250
255
  <MessageContent
256
+ className={messageContainer}
251
257
  editing={editing}
252
258
  id={id}
253
259
  markdownProps={markdownProps}
@@ -17,6 +17,14 @@ export default {
17
17
  localFiles: {
18
18
  file: '文件',
19
19
  folder: '文件夹',
20
+ moveFiles: {
21
+ itemsMoved: '已移动 {{count}} 个项目:',
22
+ itemsMoved_one: '已移动 {{count}} 个项目:',
23
+ itemsMoved_other: '已移动 {{count}} 个项目:',
24
+ itemsToMove: '{{count}} 个项目待移动:',
25
+ itemsToMove_one: '{{count}} 个项目待移动:',
26
+ itemsToMove_other: '{{count}} 个项目待移动:',
27
+ },
20
28
  open: '打开',
21
29
  openFile: '打开文件',
22
30
  openFolder: '打开文件夹',
@@ -252,7 +252,7 @@ export const localSystemSlice: StateCreator<
252
252
  if (result.shell_id) {
253
253
  message = `Command started in background with shell_id: ${result.shell_id}`;
254
254
  } else {
255
- message = `Command completed successfully. Exit code: ${result.exit_code}`;
255
+ message = `Command completed successfully.`;
256
256
  }
257
257
  } else {
258
258
  message = `Command failed: ${result.error}`;
@@ -1,7 +1,7 @@
1
1
  import { BuiltinIntervention } from '@lobechat/types';
2
2
 
3
- import { LocalSystemApiName, LocalSystemManifest } from './local-system';
4
- import RunCommand from './local-system/Intervention/RunCommand';
3
+ import { LocalSystemManifest } from './local-system';
4
+ import { LocalSystemInterventions } from './local-system/Intervention';
5
5
 
6
6
  /**
7
7
  * Builtin tools interventions registry
@@ -9,9 +9,7 @@ import RunCommand from './local-system/Intervention/RunCommand';
9
9
  * Only register APIs that have custom intervention UI
10
10
  */
11
11
  export const BuiltinToolInterventions: Record<string, Record<string, any>> = {
12
- [LocalSystemManifest.identifier]: {
13
- [LocalSystemApiName.runCommand]: RunCommand,
14
- },
12
+ [LocalSystemManifest.identifier]: LocalSystemInterventions,
15
13
  };
16
14
 
17
15
  /**
@@ -0,0 +1,56 @@
1
+ import { Icon, Text } from '@lobehub/ui';
2
+ import { createStyles } from 'antd-style';
3
+ import { ArrowRight } from 'lucide-react';
4
+ import { memo } from 'react';
5
+ import { Flexbox } from 'react-layout-kit';
6
+
7
+ import { useElectronStore } from '@/store/electron';
8
+ import { desktopStateSelectors } from '@/store/electron/selectors';
9
+
10
+ const useStyles = createStyles(({ css, token }) => ({
11
+ icon: css`
12
+ color: ${token.colorTextQuaternary};
13
+ `,
14
+ item: css`
15
+ padding-block: 4px;
16
+ padding-inline: 12px;
17
+ border-radius: ${token.borderRadius}px;
18
+ transition: all 0.2s ease;
19
+
20
+ &:hover {
21
+ background: ${token.colorFillQuaternary};
22
+ }
23
+ `,
24
+ path: css`
25
+ font-family: ${token.fontFamilyCode};
26
+ font-size: 12px;
27
+ word-break: break-all;
28
+ `,
29
+ }));
30
+
31
+ interface MoveFileItemProps {
32
+ newPath: string;
33
+ oldPath: string;
34
+ }
35
+
36
+ const MoveFileItem = memo<MoveFileItemProps>(({ oldPath, newPath }) => {
37
+ const { styles } = useStyles();
38
+ const displayOldPath = useElectronStore(desktopStateSelectors.displayRelativePath(oldPath));
39
+ const displayNewPath = useElectronStore(desktopStateSelectors.displayRelativePath(newPath));
40
+
41
+ return (
42
+ <Flexbox align="center" className={styles.item} gap={8} horizontal width="100%">
43
+ <Flexbox flex={1}>
44
+ <Text className={styles.path} type="secondary">
45
+ {displayOldPath}
46
+ </Text>
47
+ </Flexbox>
48
+ <Icon className={styles.icon} icon={ArrowRight} />
49
+ <Flexbox flex={2}>
50
+ <Text className={styles.path}>{displayNewPath}</Text>
51
+ </Flexbox>
52
+ </Flexbox>
53
+ );
54
+ });
55
+
56
+ export default MoveFileItem;
@@ -0,0 +1,26 @@
1
+ import { MoveLocalFilesParams } from '@lobechat/electron-client-ipc';
2
+ import { BuiltinInterventionProps } from '@lobechat/types';
3
+ import { Text } from '@lobehub/ui';
4
+ import { memo } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+ import { Flexbox } from 'react-layout-kit';
7
+
8
+ import MoveFileItem from './MoveFileItem';
9
+
10
+ const MoveLocalFiles = memo<BuiltinInterventionProps<MoveLocalFilesParams>>(({ args }) => {
11
+ const { items } = args;
12
+ const { t } = useTranslation('tool');
13
+
14
+ return (
15
+ <Flexbox gap={8}>
16
+ <Text type="secondary">{t('localFiles.moveFiles.itemsToMove', { count: items.length })}</Text>
17
+ <Flexbox gap={6}>
18
+ {items.map((item, index) => (
19
+ <MoveFileItem key={index} newPath={item.newPath} oldPath={item.oldPath} />
20
+ ))}
21
+ </Flexbox>
22
+ </Flexbox>
23
+ );
24
+ });
25
+
26
+ export default MoveLocalFiles;
@@ -1,10 +1,9 @@
1
1
  import { RunCommandParams } from '@lobechat/electron-client-ipc';
2
+ import { BuiltinInterventionProps } from '@lobechat/types';
2
3
  import { Highlighter, Text } from '@lobehub/ui';
3
4
  import { memo } from 'react';
4
5
  import { Flexbox } from 'react-layout-kit';
5
6
 
6
- import { BuiltinInterventionProps } from '@/types/tool';
7
-
8
7
  const formatTimeout = (ms?: number) => {
9
8
  if (!ms) return null;
10
9
 
@@ -0,0 +1,11 @@
1
+ import { LocalSystemApiName } from '../index';
2
+ import MoveLocalFiles from './MoveLocalFiles';
3
+ import RunCommand from './RunCommand';
4
+
5
+ /**
6
+ * Local System Intervention Components Registry
7
+ */
8
+ export const LocalSystemInterventions = {
9
+ [LocalSystemApiName.moveLocalFiles]: MoveLocalFiles,
10
+ [LocalSystemApiName.runCommand]: RunCommand,
11
+ };
@@ -0,0 +1,56 @@
1
+ import { Icon, Text } from '@lobehub/ui';
2
+ import { createStyles } from 'antd-style';
3
+ import { ArrowRight } from 'lucide-react';
4
+ import { memo } from 'react';
5
+ import { Flexbox } from 'react-layout-kit';
6
+
7
+ import { useElectronStore } from '@/store/electron';
8
+ import { desktopStateSelectors } from '@/store/electron/selectors';
9
+
10
+ const useStyles = createStyles(({ css, token }) => ({
11
+ icon: css`
12
+ color: ${token.colorTextQuaternary};
13
+ `,
14
+ item: css`
15
+ padding-block: 4px;
16
+ padding-inline: 12px;
17
+ border-radius: ${token.borderRadius}px;
18
+ transition: all 0.2s ease;
19
+
20
+ &:hover {
21
+ background: ${token.colorFillQuaternary};
22
+ }
23
+ `,
24
+ path: css`
25
+ font-family: ${token.fontFamilyCode};
26
+ font-size: 12px;
27
+ word-break: break-all;
28
+ `,
29
+ }));
30
+
31
+ interface MoveFileItemProps {
32
+ newPath: string;
33
+ oldPath: string;
34
+ }
35
+
36
+ const MoveFileItem = memo<MoveFileItemProps>(({ oldPath, newPath }) => {
37
+ const { styles } = useStyles();
38
+ const displayOldPath = useElectronStore(desktopStateSelectors.displayRelativePath(oldPath));
39
+ const displayNewPath = useElectronStore(desktopStateSelectors.displayRelativePath(newPath));
40
+
41
+ return (
42
+ <Flexbox align="center" className={styles.item} gap={8} horizontal width="100%">
43
+ <Flexbox flex={1}>
44
+ <Text className={styles.path} type="secondary">
45
+ {displayOldPath}
46
+ </Text>
47
+ </Flexbox>
48
+ <Icon className={styles.icon} icon={ArrowRight} />
49
+ <Flexbox flex={2}>
50
+ <Text className={styles.path}>{displayNewPath}</Text>
51
+ </Flexbox>
52
+ </Flexbox>
53
+ );
54
+ });
55
+
56
+ export default MoveFileItem;
@@ -0,0 +1,26 @@
1
+ import { MoveLocalFilesParams } from '@lobechat/electron-client-ipc';
2
+ import { BuiltinRenderProps } from '@lobechat/types';
3
+ import { Text } from '@lobehub/ui';
4
+ import { memo } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+ import { Flexbox } from 'react-layout-kit';
7
+
8
+ import MoveFileItem from './MoveFileItem';
9
+
10
+ const MoveLocalFiles = memo<BuiltinRenderProps<MoveLocalFilesParams>>(({ args }) => {
11
+ const { items } = args;
12
+ const { t } = useTranslation('tool');
13
+
14
+ return (
15
+ <Flexbox gap={8}>
16
+ <Text type="secondary">{t('localFiles.moveFiles.itemsMoved', { count: items.length })}</Text>
17
+ <Flexbox gap={6}>
18
+ {items.map((item, index) => (
19
+ <MoveFileItem key={index} newPath={item.newPath} oldPath={item.oldPath} />
20
+ ))}
21
+ </Flexbox>
22
+ </Flexbox>
23
+ );
24
+ });
25
+
26
+ export default MoveLocalFiles;
@@ -0,0 +1,21 @@
1
+ import { LocalSystemApiName } from '../index';
2
+ import ListFiles from './ListFiles';
3
+ import MoveLocalFiles from './MoveLocalFiles';
4
+ import ReadLocalFile from './ReadLocalFile';
5
+ import RenameLocalFile from './RenameLocalFile';
6
+ import RunCommand from './RunCommand';
7
+ import SearchFiles from './SearchFiles';
8
+ import WriteFile from './WriteFile';
9
+
10
+ /**
11
+ * Local System Render Components Registry
12
+ */
13
+ export const LocalSystemRenders = {
14
+ [LocalSystemApiName.listLocalFiles]: ListFiles,
15
+ [LocalSystemApiName.moveLocalFiles]: MoveLocalFiles,
16
+ [LocalSystemApiName.readLocalFile]: ReadLocalFile,
17
+ [LocalSystemApiName.renameLocalFile]: RenameLocalFile,
18
+ [LocalSystemApiName.runCommand]: RunCommand,
19
+ [LocalSystemApiName.searchLocalFiles]: SearchFiles,
20
+ [LocalSystemApiName.writeLocalFile]: WriteFile,
21
+ };
@@ -3,37 +3,19 @@ import { BuiltinRender } from '@lobechat/types';
3
3
  import { CodeInterpreterManifest } from './code-interpreter';
4
4
  import CodeInterpreterRender from './code-interpreter/Render';
5
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';
6
+ import { LocalSystemManifest } from './local-system';
7
+ import { LocalSystemRenders } from './local-system/Render';
13
8
  // 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';
9
+ import { WebBrowsingManifest } from './web-browsing';
10
+ import { WebBrowsingRenders } from './web-browsing/Render';
18
11
 
19
12
  /**
20
13
  * Builtin tools renders registry
21
14
  * Organized by toolset (identifier) -> API name
22
15
  */
23
16
  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
- },
17
+ [LocalSystemManifest.identifier]: LocalSystemRenders as Record<string, BuiltinRender>,
18
+ [WebBrowsingManifest.identifier]: WebBrowsingRenders as Record<string, BuiltinRender>,
37
19
  [CodeInterpreterManifest.identifier]: {
38
20
  python: CodeInterpreterRender as BuiltinRender,
39
21
  },
@@ -0,0 +1,13 @@
1
+ import { WebBrowsingApiName } from '../index';
2
+ import CrawlMultiPages from './CrawlMultiPages';
3
+ import CrawlSinglePage from './CrawlSinglePage';
4
+ import Search from './Search';
5
+
6
+ /**
7
+ * Web Browsing Render Components Registry
8
+ */
9
+ export const WebBrowsingRenders = {
10
+ [WebBrowsingApiName.crawlMultiPages]: CrawlMultiPages,
11
+ [WebBrowsingApiName.crawlSinglePage]: CrawlSinglePage,
12
+ [WebBrowsingApiName.search]: Search,
13
+ };