@lobehub/lobehub 2.0.0-next.183 → 2.0.0-next.185

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 (128) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v1.json +18 -0
  3. package/locales/ar/auth.json +1 -0
  4. package/locales/ar/models.json +40 -0
  5. package/locales/ar/setting.json +1 -0
  6. package/locales/ar/subscription.json +13 -0
  7. package/locales/bg-BG/auth.json +1 -0
  8. package/locales/bg-BG/models.json +22 -0
  9. package/locales/bg-BG/setting.json +1 -0
  10. package/locales/bg-BG/subscription.json +13 -0
  11. package/locales/de-DE/auth.json +1 -0
  12. package/locales/de-DE/models.json +37 -0
  13. package/locales/de-DE/setting.json +1 -0
  14. package/locales/de-DE/subscription.json +13 -0
  15. package/locales/en-US/auth.json +1 -0
  16. package/locales/en-US/setting.json +1 -1
  17. package/locales/es-ES/auth.json +1 -0
  18. package/locales/es-ES/models.json +30 -0
  19. package/locales/es-ES/setting.json +1 -0
  20. package/locales/es-ES/subscription.json +13 -0
  21. package/locales/fa-IR/auth.json +1 -0
  22. package/locales/fa-IR/models.json +31 -0
  23. package/locales/fa-IR/setting.json +1 -0
  24. package/locales/fa-IR/subscription.json +13 -0
  25. package/locales/fr-FR/auth.json +1 -0
  26. package/locales/fr-FR/models.json +17 -0
  27. package/locales/fr-FR/setting.json +1 -0
  28. package/locales/fr-FR/subscription.json +13 -0
  29. package/locales/it-IT/auth.json +1 -0
  30. package/locales/it-IT/models.json +31 -0
  31. package/locales/it-IT/setting.json +1 -0
  32. package/locales/it-IT/subscription.json +13 -0
  33. package/locales/ja-JP/auth.json +1 -0
  34. package/locales/ja-JP/models.json +1 -0
  35. package/locales/ja-JP/setting.json +1 -0
  36. package/locales/ja-JP/subscription.json +13 -0
  37. package/locales/ko-KR/auth.json +1 -0
  38. package/locales/ko-KR/models.json +39 -0
  39. package/locales/ko-KR/setting.json +1 -0
  40. package/locales/ko-KR/subscription.json +13 -0
  41. package/locales/nl-NL/auth.json +1 -0
  42. package/locales/nl-NL/models.json +35 -0
  43. package/locales/nl-NL/setting.json +1 -0
  44. package/locales/nl-NL/subscription.json +13 -0
  45. package/locales/pl-PL/auth.json +1 -0
  46. package/locales/pl-PL/models.json +12 -0
  47. package/locales/pl-PL/setting.json +1 -0
  48. package/locales/pl-PL/subscription.json +13 -0
  49. package/locales/pt-BR/auth.json +1 -0
  50. package/locales/pt-BR/models.json +1 -0
  51. package/locales/pt-BR/setting.json +1 -0
  52. package/locales/pt-BR/subscription.json +13 -0
  53. package/locales/ru-RU/auth.json +1 -0
  54. package/locales/ru-RU/models.json +32 -0
  55. package/locales/ru-RU/setting.json +1 -0
  56. package/locales/ru-RU/subscription.json +13 -0
  57. package/locales/tr-TR/auth.json +1 -0
  58. package/locales/tr-TR/models.json +20 -0
  59. package/locales/tr-TR/setting.json +1 -0
  60. package/locales/tr-TR/subscription.json +13 -0
  61. package/locales/vi-VN/auth.json +1 -0
  62. package/locales/vi-VN/models.json +39 -0
  63. package/locales/vi-VN/setting.json +1 -0
  64. package/locales/vi-VN/subscription.json +13 -0
  65. package/locales/zh-CN/auth.json +1 -0
  66. package/locales/zh-CN/models.json +49 -0
  67. package/locales/zh-CN/setting.json +1 -1
  68. package/locales/zh-TW/auth.json +1 -0
  69. package/locales/zh-TW/models.json +23 -0
  70. package/locales/zh-TW/setting.json +1 -0
  71. package/locales/zh-TW/subscription.json +13 -0
  72. package/package.json +1 -1
  73. package/packages/builtin-tool-local-system/package.json +10 -0
  74. package/packages/builtin-tool-local-system/src/client/Inspector/EditLocalFile/index.tsx +81 -0
  75. package/packages/builtin-tool-local-system/src/client/Inspector/GlobLocalFiles/index.tsx +73 -0
  76. package/packages/builtin-tool-local-system/src/client/Inspector/GrepContent/index.tsx +73 -0
  77. package/packages/builtin-tool-local-system/src/client/Inspector/ReadLocalFile/index.tsx +81 -0
  78. package/packages/builtin-tool-local-system/src/client/Inspector/RunCommand/index.tsx +80 -0
  79. package/packages/builtin-tool-local-system/src/client/Inspector/SearchLocalFiles/index.tsx +71 -0
  80. package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Inspector/index.ts +1 -2
  81. package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Intervention/index.ts +1 -2
  82. package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/ListFiles/Result.tsx +2 -1
  83. package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/index.ts +1 -2
  84. package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Streaming/index.ts +1 -2
  85. package/packages/builtin-tool-local-system/src/client/index.ts +20 -0
  86. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/index.tsx +3 -3
  87. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/index.tsx +3 -3
  88. package/src/app/[variants]/(main)/home/_layout/Body/Agent/index.tsx +3 -3
  89. package/src/app/[variants]/(main)/home/features/RecentPage/index.tsx +3 -2
  90. package/src/app/[variants]/(main)/home/features/RecentResource/index.tsx +3 -2
  91. package/src/app/[variants]/(main)/home/features/RecentTopic/index.tsx +3 -3
  92. package/src/components/NeuralNetworkLoading/index.tsx +181 -0
  93. package/src/libs/swr/index.ts +1 -8
  94. package/src/store/image/utils/size.test.ts +245 -0
  95. package/src/tools/inspectors.ts +6 -5
  96. package/src/tools/interventions.ts +5 -4
  97. package/src/tools/placeholders.ts +9 -7
  98. package/src/tools/renders.ts +5 -3
  99. package/src/tools/streamings.ts +6 -5
  100. package/src/tools/local-system/Inspector/EditLocalFile/index.tsx +0 -55
  101. package/src/tools/local-system/Inspector/GlobLocalFiles/index.tsx +0 -59
  102. package/src/tools/local-system/Inspector/GrepContent/index.tsx +0 -59
  103. package/src/tools/local-system/Inspector/ReadLocalFile/index.tsx +0 -55
  104. package/src/tools/local-system/Inspector/RunCommand/index.tsx +0 -66
  105. package/src/tools/local-system/Inspector/SearchLocalFiles/index.tsx +0 -59
  106. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Intervention/EditLocalFile/index.tsx +0 -0
  107. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Intervention/MoveLocalFiles/MoveFileItem.tsx +0 -0
  108. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Intervention/MoveLocalFiles/index.tsx +0 -0
  109. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Intervention/RunCommand/index.tsx +0 -0
  110. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Intervention/WriteFile/index.tsx +0 -0
  111. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Placeholder/ListFiles.tsx +0 -0
  112. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Placeholder/SearchFiles.tsx +0 -0
  113. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/EditLocalFile/index.tsx +0 -0
  114. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/ListFiles/index.tsx +0 -0
  115. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/MoveLocalFiles/MoveFileItem.tsx +0 -0
  116. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/MoveLocalFiles/index.tsx +0 -0
  117. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/ReadLocalFile/ReadFileSkeleton.tsx +0 -0
  118. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/ReadLocalFile/ReadFileView.tsx +0 -0
  119. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/ReadLocalFile/index.tsx +0 -0
  120. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/RenameLocalFile/index.tsx +0 -0
  121. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/RunCommand/index.tsx +0 -0
  122. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/SearchFiles/Result.tsx +0 -0
  123. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/SearchFiles/SearchQuery/SearchView.tsx +0 -0
  124. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/SearchFiles/SearchQuery/index.tsx +0 -0
  125. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/SearchFiles/index.tsx +0 -0
  126. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Render/WriteFile/index.tsx +0 -0
  127. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/Streaming/RunCommand/index.tsx +0 -0
  128. /package/{src/tools/local-system → packages/builtin-tool-local-system/src/client}/components/FileItem.tsx +0 -0
@@ -1,10 +1,10 @@
1
1
  'use client';
2
2
 
3
- import { AccordionItem, ActionIcon, Dropdown, Flexbox, Text } from '@lobehub/ui';
4
- import { Loader2Icon } from 'lucide-react';
3
+ import { AccordionItem, Dropdown, Flexbox, Text } from '@lobehub/ui';
5
4
  import React, { Suspense, memo } from 'react';
6
5
  import { useTranslation } from 'react-i18next';
7
6
 
7
+ import NeuralNetworkLoading from '@/components/NeuralNetworkLoading';
8
8
  import SkeletonList from '@/features/NavPanel/components/SkeletonList';
9
9
  import { useFetchTopics } from '@/hooks/useFetchTopics';
10
10
  import { useChatStore } from '@/store/chat';
@@ -45,7 +45,7 @@ const Topic = memo<TopicProps>(({ itemKey }) => {
45
45
  <Text ellipsis fontSize={12} type={'secondary'} weight={500}>
46
46
  {`${t('title')} ${topicCount > 0 ? topicCount : ''}`}
47
47
  </Text>
48
- {isRevalidating && <ActionIcon icon={Loader2Icon} loading size={'small'} />}
48
+ {isRevalidating && <NeuralNetworkLoading size={14} />}
49
49
  </Flexbox>
50
50
  }
51
51
  >
@@ -1,10 +1,10 @@
1
1
  'use client';
2
2
 
3
- import { AccordionItem, ActionIcon, Dropdown, Flexbox, Text } from '@lobehub/ui';
4
- import { Loader2Icon } from 'lucide-react';
3
+ import { AccordionItem, Dropdown, Flexbox, Text } from '@lobehub/ui';
5
4
  import React, { Suspense, memo } from 'react';
6
5
  import { useTranslation } from 'react-i18next';
7
6
 
7
+ import NeuralNetworkLoading from '@/components/NeuralNetworkLoading';
8
8
  import SkeletonList from '@/features/NavPanel/components/SkeletonList';
9
9
  import { useFetchTopics } from '@/hooks/useFetchTopics';
10
10
  import { useChatStore } from '@/store/chat';
@@ -45,7 +45,7 @@ const Topic = memo<TopicProps>(({ itemKey }) => {
45
45
  <Text ellipsis fontSize={12} type={'secondary'} weight={500}>
46
46
  {`${t('title')} ${topicCount > 0 ? topicCount : ''}`}
47
47
  </Text>
48
- {isRevalidating && <ActionIcon icon={Loader2Icon} loading size={'small'} />}
48
+ {isRevalidating && <NeuralNetworkLoading size={14} />}
49
49
  </Flexbox>
50
50
  }
51
51
  >
@@ -1,10 +1,10 @@
1
1
  'use client';
2
2
 
3
- import { AccordionItem, ActionIcon, Dropdown, Flexbox, Text } from '@lobehub/ui';
4
- import { Loader2Icon } from 'lucide-react';
3
+ import { AccordionItem, Dropdown, Flexbox, Text } from '@lobehub/ui';
5
4
  import React, { Suspense, memo, useCallback } from 'react';
6
5
  import { useTranslation } from 'react-i18next';
7
6
 
7
+ import NeuralNetworkLoading from '@/components/NeuralNetworkLoading';
8
8
  import { useFetchAgentList } from '@/hooks/useFetchAgentList';
9
9
 
10
10
  import SkeletonList from '../../../../../../../features/NavPanel/components/SkeletonList';
@@ -56,7 +56,7 @@ const Agent = memo<AgentProps>(({ itemKey }) => {
56
56
  <Text ellipsis fontSize={12} type={'secondary'} weight={500}>
57
57
  {t('navPanel.agent')}
58
58
  </Text>
59
- {isRevalidating && <ActionIcon icon={Loader2Icon} loading size={'small'} />}
59
+ {isRevalidating && <NeuralNetworkLoading size={14} />}
60
60
  </Flexbox>
61
61
  }
62
62
  >
@@ -1,12 +1,13 @@
1
1
  'use client';
2
2
 
3
3
  import { ActionIcon, Dropdown } from '@lobehub/ui';
4
- import { FileTextIcon, Loader2Icon, MoreHorizontal } from 'lucide-react';
4
+ import { FileTextIcon, MoreHorizontal } from 'lucide-react';
5
5
  import { Suspense, memo } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { useNavigate } from 'react-router-dom';
8
8
 
9
9
  import { useResourceManagerStore } from '@/app/[variants]/(main)/resource/features/store';
10
+ import NeuralNetworkLoading from '@/components/NeuralNetworkLoading';
10
11
  import { useInitRecentPage } from '@/hooks/useInitRecentPage';
11
12
  import { useHomeStore } from '@/store/home';
12
13
  import { homeRecentSelectors } from '@/store/home/selectors';
@@ -35,7 +36,7 @@ const RecentPage = memo(() => {
35
36
  <GroupBlock
36
37
  action={
37
38
  <>
38
- {isRevalidating && <ActionIcon icon={Loader2Icon} loading size={'small'} />}
39
+ {isRevalidating && <NeuralNetworkLoading size={14} />}
39
40
  <Dropdown
40
41
  menu={{
41
42
  items: [
@@ -1,12 +1,13 @@
1
1
  'use client';
2
2
 
3
3
  import { ActionIcon, Dropdown } from '@lobehub/ui';
4
- import { Clock, Loader2Icon, MoreHorizontal } from 'lucide-react';
4
+ import { Clock, MoreHorizontal } from 'lucide-react';
5
5
  import { Suspense, memo } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { useNavigate } from 'react-router-dom';
8
8
 
9
9
  import { useResourceManagerStore } from '@/app/[variants]/(main)/resource/features/store';
10
+ import NeuralNetworkLoading from '@/components/NeuralNetworkLoading';
10
11
  import { useInitRecentResource } from '@/hooks/useInitRecentResource';
11
12
  import { useHomeStore } from '@/store/home';
12
13
  import { homeRecentSelectors } from '@/store/home/selectors';
@@ -35,7 +36,7 @@ const RecentResource = memo(() => {
35
36
  <GroupBlock
36
37
  action={
37
38
  <>
38
- {isRevalidating && <ActionIcon icon={Loader2Icon} loading size={'small'} />}
39
+ {isRevalidating && <NeuralNetworkLoading size={14} />}
39
40
  <Dropdown
40
41
  menu={{
41
42
  items: [
@@ -1,8 +1,8 @@
1
- import { ActionIcon } from '@lobehub/ui';
2
- import { BotMessageSquareIcon, Loader2Icon } from 'lucide-react';
1
+ import { BotMessageSquareIcon } from 'lucide-react';
3
2
  import { Suspense, memo } from 'react';
4
3
  import { useTranslation } from 'react-i18next';
5
4
 
5
+ import NeuralNetworkLoading from '@/components/NeuralNetworkLoading';
6
6
  import { useInitRecentTopic } from '@/hooks/useInitRecentTopic';
7
7
  import { useHomeStore } from '@/store/home';
8
8
  import { homeRecentSelectors } from '@/store/home/selectors';
@@ -26,7 +26,7 @@ const RecentTopic = memo(() => {
26
26
 
27
27
  return (
28
28
  <GroupBlock
29
- action={isRevalidating && <ActionIcon icon={Loader2Icon} loading size={'small'} />}
29
+ action={isRevalidating && <NeuralNetworkLoading size={14} />}
30
30
  icon={BotMessageSquareIcon}
31
31
  title={t('topic.recent')}
32
32
  >
@@ -0,0 +1,181 @@
1
+ 'use client';
2
+
3
+ import { createStaticStyles, keyframes } from 'antd-style';
4
+ import { CSSProperties, memo } from 'react';
5
+
6
+ const pulseAnim = keyframes`
7
+ 0%, 100% {
8
+ opacity: 0.3;
9
+ }
10
+ 50% {
11
+ opacity: 1;
12
+ }
13
+ `;
14
+
15
+ const flowAnim = keyframes`
16
+ 0% {
17
+ transform: translateX(0);
18
+ opacity: 0.5;
19
+ }
20
+ 50% {
21
+ opacity: 1;
22
+ }
23
+ 100% {
24
+ transform: translateX(var(--flow-distance));
25
+ opacity: 0.5;
26
+ }
27
+ `;
28
+
29
+ const rotateAnim = keyframes`
30
+ 100% {
31
+ transform: rotate(360deg);
32
+ }
33
+ `;
34
+
35
+ const scaleAnim = keyframes`
36
+ 0%, 100% {
37
+ transform: scale(0.8);
38
+ opacity: 0.5;
39
+ }
40
+ 50% {
41
+ transform: scale(1);
42
+ opacity: 1;
43
+ }
44
+ `;
45
+
46
+ const styles = createStaticStyles(({ css, cssVar }) => ({
47
+ center: css`
48
+ fill: ${cssVar.colorTextSecondary};
49
+ animation: ${scaleAnim} 2s infinite;
50
+ `,
51
+
52
+ connection: css`
53
+ opacity: 0.3;
54
+ stroke: ${cssVar.colorTextSecondary};
55
+ stroke-width: 0.5;
56
+ `,
57
+
58
+ container: css`
59
+ display: flex;
60
+ align-items: center;
61
+ justify-content: center;
62
+ `,
63
+
64
+ node: css`
65
+ fill: ${cssVar.colorTextSecondary};
66
+ animation: ${pulseAnim} 2s infinite;
67
+ `,
68
+
69
+ particle: css`
70
+ fill: ${cssVar.colorTextSecondary};
71
+ animation: ${flowAnim} 2s infinite;
72
+ `,
73
+
74
+ ring: css`
75
+ transform-origin: center;
76
+
77
+ fill: none;
78
+ stroke: ${cssVar.colorFill};
79
+ stroke-dasharray: 0 8;
80
+ stroke-width: 1;
81
+
82
+ animation: ${rotateAnim} 20s infinite linear;
83
+ `,
84
+
85
+ svg: css`
86
+ width: 100%;
87
+ height: 100%;
88
+ `,
89
+ }));
90
+
91
+ interface NeuralNetworkLoadingProps {
92
+ size?: number;
93
+ }
94
+
95
+ const NeuralNetworkLoading = memo<NeuralNetworkLoadingProps>(({ size = 16 }) => {
96
+ const nodeCount = 3;
97
+ const layerCount = 3;
98
+
99
+ // Generate nodes for each layer
100
+ const nodes = [];
101
+ for (let layerIndex = 0; layerIndex < layerCount; layerIndex++) {
102
+ for (let nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) {
103
+ const x = 25 + layerIndex * 25;
104
+ const y = 25 + nodeIndex * 25;
105
+ const delay = (layerIndex * nodeCount + nodeIndex) * 0.2;
106
+ nodes.push(
107
+ <circle
108
+ className={styles.node}
109
+ cx={x}
110
+ cy={y}
111
+ key={`node-${layerIndex}-${nodeIndex}`}
112
+ r="3"
113
+ style={{ animationDelay: `${delay}s` }}
114
+ />,
115
+ );
116
+ }
117
+ }
118
+
119
+ // Generate connections between layers
120
+ const connections = [];
121
+ for (let layerIndex = 0; layerIndex < layerCount - 1; layerIndex++) {
122
+ for (let nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) {
123
+ const x1 = 25 + layerIndex * 25;
124
+ const y1 = 25 + nodeIndex * 25;
125
+ for (let targetIndex = 0; targetIndex < nodeCount; targetIndex++) {
126
+ const x2 = 25 + (layerIndex + 1) * 25;
127
+ const y2 = 25 + targetIndex * 25;
128
+ connections.push(
129
+ <line
130
+ className={styles.connection}
131
+ key={`connection-${layerIndex}-${nodeIndex}-${targetIndex}`}
132
+ x1={x1}
133
+ x2={x2}
134
+ y1={y1}
135
+ y2={y2}
136
+ />,
137
+ );
138
+ }
139
+ }
140
+ }
141
+
142
+ // Generate particles
143
+ const particles = [0, 1, 2].map((index) => (
144
+ <circle
145
+ className={styles.particle}
146
+ cx={25}
147
+ cy={50}
148
+ key={`particle-${index}`}
149
+ r="1.5"
150
+ style={
151
+ {
152
+ '--flow-distance': '50px',
153
+ 'animationDelay': `${index * 0.6}s`,
154
+ } as CSSProperties
155
+ }
156
+ />
157
+ ));
158
+
159
+ return (
160
+ <div className={styles.container} style={{ height: size, width: size }}>
161
+ <svg className={styles.svg} viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
162
+ {/* Connections */}
163
+ {connections}
164
+
165
+ {/* Nodes */}
166
+ {nodes}
167
+
168
+ {/* Particles */}
169
+ {particles}
170
+
171
+ {/* Central processing unit */}
172
+ <rect className={styles.center} height="6" width="6" x="47" y="47" />
173
+
174
+ {/* Rotating outer ring */}
175
+ <circle className={styles.ring} cx="50" cy="50" r="40" />
176
+ </svg>
177
+ </div>
178
+ );
179
+ });
180
+
181
+ export default NeuralNetworkLoading;
@@ -1,6 +1,5 @@
1
1
  import useSWR, { type SWRHook } from 'swr';
2
2
 
3
- import { isDesktop } from '@/const/version';
4
3
 
5
4
  /**
6
5
  * This type of request method is relatively flexible data, which will be triggered on the first time
@@ -27,13 +26,7 @@ export const useClientDataSWR: SWRHook = (key, fetch, config) =>
27
26
  // Cause issue like this: https://github.com/lobehub/lobe-chat/issues/532
28
27
  // we need to set it to 0.
29
28
  dedupingInterval: 0,
30
- focusThrottleInterval:
31
- // FIXME: desktop 云同步模式也是走 edge 请求,也应该增大延迟
32
- // desktop 1.5s
33
- isDesktop
34
- ? 1500
35
- : // web 300s
36
- 5 * 60 * 1000,
29
+ focusThrottleInterval: 5 * 60 * 1000,
37
30
  // Custom error retry logic: don't retry on 401 errors
38
31
  onErrorRetry: (error: any, key: any, config: any, revalidate: any, { retryCount }: any) => {
39
32
  // Check if error is marked as non-retryable (e.g., 401 authentication errors)
@@ -0,0 +1,245 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { adaptSizeToRatio, parseRatio } from './size';
4
+
5
+ describe('size utils', () => {
6
+ describe('parseRatio', () => {
7
+ it('should parse valid ratio string correctly', () => {
8
+ expect(parseRatio('16:9')).toBe(16 / 9);
9
+ expect(parseRatio('4:3')).toBe(4 / 3);
10
+ expect(parseRatio('1:1')).toBe(1);
11
+ expect(parseRatio('21:9')).toBe(21 / 9);
12
+ });
13
+
14
+ it('should handle square ratio correctly', () => {
15
+ expect(parseRatio('1:1')).toBe(1);
16
+ expect(parseRatio('100:100')).toBe(1);
17
+ expect(parseRatio('512:512')).toBe(1);
18
+ });
19
+
20
+ it('should handle wide ratios correctly', () => {
21
+ expect(parseRatio('16:9')).toBeCloseTo(16 / 9, 6);
22
+ expect(parseRatio('2:1')).toBe(2);
23
+ expect(parseRatio('3:1')).toBe(3);
24
+ });
25
+
26
+ it('should handle tall ratios correctly', () => {
27
+ expect(parseRatio('9:16')).toBeCloseTo(0.5625, 4);
28
+ expect(parseRatio('1:2')).toBe(0.5);
29
+ expect(parseRatio('3:4')).toBe(0.75);
30
+ });
31
+
32
+ it('should handle decimal values in ratio string', () => {
33
+ expect(parseRatio('1.5:1')).toBe(1.5);
34
+ expect(parseRatio('16.5:9.5')).toBeCloseTo(16.5 / 9.5, 6);
35
+ });
36
+
37
+ it('should return 1 for invalid ratio string formats', () => {
38
+ expect(parseRatio('16')).toBe(1); // Missing colon
39
+ expect(parseRatio('16-9')).toBe(1); // Wrong separator
40
+ expect(parseRatio('16:9:1')).toBe(1); // Too many parts
41
+ expect(parseRatio('')).toBe(1); // Empty string
42
+ expect(parseRatio(':')).toBe(1); // Only separator
43
+ });
44
+
45
+ it('should return 1 for invalid input types', () => {
46
+ // @ts-expect-error - testing runtime behavior with invalid types
47
+ expect(parseRatio(null)).toBe(1);
48
+ // @ts-expect-error - testing runtime behavior with invalid types
49
+ expect(parseRatio(undefined)).toBe(1);
50
+ // @ts-expect-error - testing runtime behavior with invalid types
51
+ expect(parseRatio(123)).toBe(1);
52
+ // @ts-expect-error - testing runtime behavior with invalid types
53
+ expect(parseRatio({})).toBe(1);
54
+ });
55
+
56
+ it('should return 1 for non-numeric ratio parts', () => {
57
+ expect(parseRatio('abc:def')).toBe(1);
58
+ expect(parseRatio('16:abc')).toBe(1);
59
+ expect(parseRatio('abc:9')).toBe(1);
60
+ expect(parseRatio('NaN:9')).toBe(1);
61
+ expect(parseRatio('16:NaN')).toBe(1);
62
+ });
63
+
64
+ it('should return 1 for zero or negative values', () => {
65
+ expect(parseRatio('0:9')).toBe(1);
66
+ expect(parseRatio('16:0')).toBe(1);
67
+ expect(parseRatio('0:0')).toBe(1);
68
+ expect(parseRatio('-16:9')).toBe(1);
69
+ expect(parseRatio('16:-9')).toBe(1);
70
+ expect(parseRatio('-16:-9')).toBe(1);
71
+ });
72
+
73
+ it('should return 1 for Infinity values', () => {
74
+ expect(parseRatio('Infinity:9')).toBe(1);
75
+ expect(parseRatio('16:Infinity')).toBe(1);
76
+ expect(parseRatio('Infinity:Infinity')).toBe(1);
77
+ });
78
+ });
79
+
80
+ describe('adaptSizeToRatio', () => {
81
+ describe('valid inputs', () => {
82
+ it('should keep width and adjust height when target ratio is wider', () => {
83
+ // 16:9 (1.777) is wider than 4:3 (1.333)
84
+ const result = adaptSizeToRatio(16 / 9, 800, 600);
85
+ expect(result).toEqual({ width: 800, height: 450 });
86
+ });
87
+
88
+ it('should keep height and adjust width when target ratio is taller', () => {
89
+ // 4:3 (1.333) is taller than 16:9 (1.777)
90
+ const result = adaptSizeToRatio(4 / 3, 800, 450);
91
+ expect(result).toEqual({ width: 600, height: 450 });
92
+ });
93
+
94
+ it('should maintain dimensions when ratio matches current ratio', () => {
95
+ // 16:9 matches 1920:1080
96
+ const result = adaptSizeToRatio(16 / 9, 1920, 1080);
97
+ expect(result).toEqual({ width: 1920, height: 1080 });
98
+ });
99
+
100
+ it('should handle square ratio (1:1) correctly', () => {
101
+ // Current ratio: 800/600 = 1.333, target ratio: 1
102
+ // Since 1 < 1.333, keeps height (600), adjusts width to 600
103
+ const result = adaptSizeToRatio(1, 800, 600);
104
+ expect(result).toEqual({ width: 600, height: 600 });
105
+
106
+ // Current ratio: 600/800 = 0.75, target ratio: 1
107
+ // Since 1 > 0.75, keeps width (600), adjusts height to 600
108
+ const result2 = adaptSizeToRatio(1, 600, 800);
109
+ expect(result2).toEqual({ width: 600, height: 600 });
110
+ });
111
+
112
+ it('should round dimensions to nearest integer', () => {
113
+ // Current ratio: 1000/800 = 1.25, target ratio: 1.5
114
+ // Since 1.5 > 1.25, keeps width (1000), adjusts height to 1000/1.5 = 666.67 -> 667
115
+ const result = adaptSizeToRatio(1.5, 1000, 800);
116
+ expect(result.width).toBe(1000);
117
+ expect(result.height).toBe(667);
118
+ expect(Number.isInteger(result.width)).toBe(true);
119
+ expect(Number.isInteger(result.height)).toBe(true);
120
+ });
121
+
122
+ it('should handle very wide ratios correctly', () => {
123
+ const result = adaptSizeToRatio(3, 1200, 800);
124
+ expect(result).toEqual({ width: 1200, height: 400 });
125
+ });
126
+
127
+ it('should handle very tall ratios correctly', () => {
128
+ const result = adaptSizeToRatio(1 / 3, 1200, 800);
129
+ expect(result).toEqual({ width: 267, height: 800 });
130
+ });
131
+
132
+ it('should handle small dimensions', () => {
133
+ const result = adaptSizeToRatio(16 / 9, 320, 240);
134
+ expect(result).toEqual({ width: 320, height: 180 });
135
+ });
136
+
137
+ it('should handle large dimensions', () => {
138
+ const result = adaptSizeToRatio(16 / 9, 3840, 2880);
139
+ expect(result).toEqual({ width: 3840, height: 2160 });
140
+ });
141
+
142
+ it('should handle decimal ratio values', () => {
143
+ const result = adaptSizeToRatio(1.5, 900, 600);
144
+ expect(result).toEqual({ width: 900, height: 600 });
145
+ });
146
+ });
147
+
148
+ describe('error handling - invalid ratio', () => {
149
+ it('should throw error for zero ratio', () => {
150
+ expect(() => adaptSizeToRatio(0, 800, 600)).toThrow(
151
+ 'Invalid ratio: must be a positive finite number',
152
+ );
153
+ });
154
+
155
+ it('should throw error for negative ratio', () => {
156
+ expect(() => adaptSizeToRatio(-1.5, 800, 600)).toThrow(
157
+ 'Invalid ratio: must be a positive finite number',
158
+ );
159
+ });
160
+
161
+ it('should throw error for NaN ratio', () => {
162
+ expect(() => adaptSizeToRatio(NaN, 800, 600)).toThrow(
163
+ 'Invalid ratio: must be a positive finite number',
164
+ );
165
+ });
166
+
167
+ it('should throw error for Infinity ratio', () => {
168
+ expect(() => adaptSizeToRatio(Infinity, 800, 600)).toThrow(
169
+ 'Invalid ratio: must be a positive finite number',
170
+ );
171
+ expect(() => adaptSizeToRatio(-Infinity, 800, 600)).toThrow(
172
+ 'Invalid ratio: must be a positive finite number',
173
+ );
174
+ });
175
+ });
176
+
177
+ describe('error handling - invalid defaultWidth', () => {
178
+ it('should throw error for zero defaultWidth', () => {
179
+ expect(() => adaptSizeToRatio(16 / 9, 0, 600)).toThrow(
180
+ 'Invalid defaultWidth: must be a positive finite number',
181
+ );
182
+ });
183
+
184
+ it('should throw error for negative defaultWidth', () => {
185
+ expect(() => adaptSizeToRatio(16 / 9, -800, 600)).toThrow(
186
+ 'Invalid defaultWidth: must be a positive finite number',
187
+ );
188
+ });
189
+
190
+ it('should throw error for NaN defaultWidth', () => {
191
+ expect(() => adaptSizeToRatio(16 / 9, NaN, 600)).toThrow(
192
+ 'Invalid defaultWidth: must be a positive finite number',
193
+ );
194
+ });
195
+
196
+ it('should throw error for Infinity defaultWidth', () => {
197
+ expect(() => adaptSizeToRatio(16 / 9, Infinity, 600)).toThrow(
198
+ 'Invalid defaultWidth: must be a positive finite number',
199
+ );
200
+ });
201
+ });
202
+
203
+ describe('error handling - invalid defaultHeight', () => {
204
+ it('should throw error for zero defaultHeight', () => {
205
+ expect(() => adaptSizeToRatio(16 / 9, 800, 0)).toThrow(
206
+ 'Invalid defaultHeight: must be a positive finite number',
207
+ );
208
+ });
209
+
210
+ it('should throw error for negative defaultHeight', () => {
211
+ expect(() => adaptSizeToRatio(16 / 9, 800, -600)).toThrow(
212
+ 'Invalid defaultHeight: must be a positive finite number',
213
+ );
214
+ });
215
+
216
+ it('should throw error for NaN defaultHeight', () => {
217
+ expect(() => adaptSizeToRatio(16 / 9, 800, NaN)).toThrow(
218
+ 'Invalid defaultHeight: must be a positive finite number',
219
+ );
220
+ });
221
+
222
+ it('should throw error for Infinity defaultHeight', () => {
223
+ expect(() => adaptSizeToRatio(16 / 9, 800, Infinity)).toThrow(
224
+ 'Invalid defaultHeight: must be a positive finite number',
225
+ );
226
+ });
227
+ });
228
+
229
+ describe('error handling - multiple invalid parameters', () => {
230
+ it('should validate ratio first before other parameters', () => {
231
+ // When multiple params are invalid, ratio is checked first
232
+ expect(() => adaptSizeToRatio(0, 0, 0)).toThrow(
233
+ 'Invalid ratio: must be a positive finite number',
234
+ );
235
+ });
236
+
237
+ it('should validate defaultWidth before defaultHeight', () => {
238
+ // When ratio is valid but width and height are invalid
239
+ expect(() => adaptSizeToRatio(1.5, 0, 0)).toThrow(
240
+ 'Invalid defaultWidth: must be a positive finite number',
241
+ );
242
+ });
243
+ });
244
+ });
245
+ });
@@ -7,16 +7,17 @@ import {
7
7
  GroupManagementManifest,
8
8
  } from '@lobechat/builtin-tool-group-management/client';
9
9
  import { GTDInspectors, GTDManifest } from '@lobechat/builtin-tool-gtd/client';
10
- import { LocalSystemManifest } from '@lobechat/builtin-tool-local-system';
11
- import { PageAgentIdentifier, PageAgentInspectors } from '@lobechat/builtin-tool-page-agent/client';
10
+ import {
11
+ LocalSystemInspectors,
12
+ LocalSystemManifest,
13
+ } from '@lobechat/builtin-tool-local-system/client';
14
+ import { PageAgentInspectors, PageAgentManifest } from '@lobechat/builtin-tool-page-agent/client';
12
15
  import {
13
16
  WebBrowsingInspectors,
14
17
  WebBrowsingManifest,
15
18
  } from '@lobechat/builtin-tool-web-browsing/client';
16
19
  import { type BuiltinInspector } from '@lobechat/types';
17
20
 
18
- import { LocalSystemInspectors } from './local-system/Inspector';
19
-
20
21
  /**
21
22
  * Builtin tools inspector registry
22
23
  * Organized by toolset (identifier) -> API name
@@ -32,7 +33,7 @@ const BuiltinToolInspectors: Record<string, Record<string, BuiltinInspector>> =
32
33
  >,
33
34
  [GTDManifest.identifier]: GTDInspectors as Record<string, BuiltinInspector>,
34
35
  [LocalSystemManifest.identifier]: LocalSystemInspectors as Record<string, BuiltinInspector>,
35
- [PageAgentIdentifier]: PageAgentInspectors as Record<string, BuiltinInspector>,
36
+ [PageAgentManifest.identifier]: PageAgentInspectors as Record<string, BuiltinInspector>,
36
37
  [WebBrowsingManifest.identifier]: WebBrowsingInspectors as Record<string, BuiltinInspector>,
37
38
  };
38
39
 
@@ -9,13 +9,14 @@ import {
9
9
  GroupManagementManifest,
10
10
  } from '@lobechat/builtin-tool-group-management/client';
11
11
  import { GTDInterventions, GTDManifest } from '@lobechat/builtin-tool-gtd/client';
12
- import { LocalSystemManifest } from '@lobechat/builtin-tool-local-system';
12
+ import {
13
+ LocalSystemIdentifier,
14
+ LocalSystemInterventions,
15
+ } from '@lobechat/builtin-tool-local-system/client';
13
16
  import { NotebookManifest } from '@lobechat/builtin-tool-notebook';
14
17
  import { NotebookInterventions } from '@lobechat/builtin-tool-notebook/client';
15
18
  import { type BuiltinIntervention } from '@lobechat/types';
16
19
 
17
- import { LocalSystemInterventions } from './local-system/Intervention';
18
-
19
20
  /**
20
21
  * Builtin tools interventions registry
21
22
  * Organized by toolset (identifier) -> API name
@@ -26,7 +27,7 @@ export const BuiltinToolInterventions: Record<string, Record<string, any>> = {
26
27
  [CloudSandboxManifest.identifier]: CloudSandboxInterventions,
27
28
  [GroupManagementManifest.identifier]: GroupManagementInterventions,
28
29
  [GTDManifest.identifier]: GTDInterventions,
29
- [LocalSystemManifest.identifier]: LocalSystemInterventions,
30
+ [LocalSystemIdentifier]: LocalSystemInterventions,
30
31
  [NotebookManifest.identifier]: NotebookInterventions,
31
32
  };
32
33
 
@@ -1,21 +1,23 @@
1
- import { LocalSystemApiName, LocalSystemManifest } from '@lobechat/builtin-tool-local-system';
1
+ import {
2
+ LocalSystemApiName,
3
+ LocalSystemIdentifier,
4
+ LocalSystemListFilesPlaceholder,
5
+ LocalSystemSearchFilesPlaceholder,
6
+ } from '@lobechat/builtin-tool-local-system/client';
2
7
  import {
3
8
  WebBrowsingManifest,
4
9
  WebBrowsingPlaceholders,
5
10
  } from '@lobechat/builtin-tool-web-browsing/client';
6
11
  import { type BuiltinPlaceholder } from '@lobechat/types';
7
12
 
8
- import { ListFiles as LocalSystemListFiles } from './local-system/Placeholder/ListFiles';
9
- import LocalSystemSearchFiles from './local-system/Placeholder/SearchFiles';
10
-
11
13
  /**
12
14
  * Builtin tools placeholders registry
13
15
  * Organized by toolset (identifier) -> API name
14
16
  */
15
17
  export const BuiltinToolPlaceholders: Record<string, Record<string, any>> = {
16
- [LocalSystemManifest.identifier]: {
17
- [LocalSystemApiName.searchLocalFiles]: LocalSystemSearchFiles,
18
- [LocalSystemApiName.listLocalFiles]: LocalSystemListFiles,
18
+ [LocalSystemIdentifier]: {
19
+ [LocalSystemApiName.searchLocalFiles]: LocalSystemSearchFilesPlaceholder,
20
+ [LocalSystemApiName.listLocalFiles]: LocalSystemListFilesPlaceholder,
19
21
  },
20
22
  [WebBrowsingManifest.identifier]: WebBrowsingPlaceholders as Record<string, any>,
21
23
  };