@lobehub/chat 1.119.1 → 1.120.0

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 (271) hide show
  1. package/.vscode/settings.json +2 -3
  2. package/CHANGELOG.md +58 -0
  3. package/changelog/v1.json +17 -0
  4. package/package.json +5 -6
  5. package/packages/const/src/auth.ts +0 -36
  6. package/packages/const/src/index.ts +3 -1
  7. package/packages/database/src/models/__tests__/aiModel.test.ts +1 -2
  8. package/packages/database/src/models/__tests__/generationBatch.test.ts +47 -1
  9. package/packages/database/src/models/aiModel.ts +2 -3
  10. package/packages/database/src/models/generationBatch.ts +8 -1
  11. package/packages/database/src/repositories/aiInfra/index.test.ts +1 -1
  12. package/packages/database/src/repositories/aiInfra/index.ts +4 -4
  13. package/packages/model-bank/src/aiModels/ai21.ts +1 -1
  14. package/packages/model-bank/src/aiModels/ai302.ts +1 -1
  15. package/packages/model-bank/src/aiModels/ai360.ts +1 -1
  16. package/packages/model-bank/src/aiModels/aihubmix.ts +3 -3
  17. package/packages/model-bank/src/aiModels/akashchat.ts +1 -1
  18. package/packages/model-bank/src/aiModels/anthropic.ts +1 -1
  19. package/packages/model-bank/src/aiModels/azure.ts +1 -1
  20. package/packages/model-bank/src/aiModels/azureai.ts +1 -1
  21. package/packages/model-bank/src/aiModels/baichuan.ts +1 -1
  22. package/packages/model-bank/src/aiModels/bedrock.ts +1 -1
  23. package/packages/model-bank/src/aiModels/bfl.ts +2 -3
  24. package/packages/model-bank/src/aiModels/cloudflare.ts +1 -1
  25. package/packages/model-bank/src/aiModels/cohere.ts +1 -1
  26. package/packages/model-bank/src/aiModels/deepseek.ts +1 -1
  27. package/packages/model-bank/src/aiModels/fal.ts +1 -1
  28. package/packages/model-bank/src/aiModels/fireworksai.ts +1 -1
  29. package/packages/model-bank/src/aiModels/giteeai.ts +1 -1
  30. package/packages/model-bank/src/aiModels/github.ts +1 -1
  31. package/packages/model-bank/src/aiModels/google.ts +6 -7
  32. package/packages/model-bank/src/aiModels/groq.ts +1 -1
  33. package/packages/model-bank/src/aiModels/higress.ts +1 -1
  34. package/packages/model-bank/src/aiModels/huggingface.ts +1 -1
  35. package/packages/model-bank/src/aiModels/hunyuan.ts +1 -1
  36. package/packages/model-bank/src/aiModels/index.ts +1 -1
  37. package/packages/model-bank/src/aiModels/infiniai.ts +1 -1
  38. package/packages/model-bank/src/aiModels/internlm.ts +1 -1
  39. package/packages/model-bank/src/aiModels/jina.ts +1 -1
  40. package/packages/model-bank/src/aiModels/lmstudio.ts +1 -1
  41. package/packages/model-bank/src/aiModels/lobehub.ts +1 -1
  42. package/packages/model-bank/src/aiModels/minimax.ts +1 -1
  43. package/packages/model-bank/src/aiModels/mistral.ts +1 -1
  44. package/packages/model-bank/src/aiModels/modelscope.ts +1 -1
  45. package/packages/model-bank/src/aiModels/moonshot.ts +1 -1
  46. package/packages/model-bank/src/aiModels/novita.ts +1 -1
  47. package/packages/model-bank/src/aiModels/nvidia.ts +1 -1
  48. package/packages/model-bank/src/aiModels/ollama.ts +1 -1
  49. package/packages/model-bank/src/aiModels/openai.ts +1 -1
  50. package/packages/model-bank/src/aiModels/openrouter.ts +3 -3
  51. package/packages/model-bank/src/aiModels/perplexity.ts +1 -1
  52. package/packages/model-bank/src/aiModels/ppio.ts +1 -1
  53. package/packages/model-bank/src/aiModels/qiniu.ts +1 -1
  54. package/packages/model-bank/src/aiModels/qwen.ts +4 -2
  55. package/packages/model-bank/src/aiModels/sambanova.ts +1 -1
  56. package/packages/model-bank/src/aiModels/search1api.ts +1 -1
  57. package/packages/model-bank/src/aiModels/sensenova.ts +1 -1
  58. package/packages/model-bank/src/aiModels/siliconcloud.ts +7 -1
  59. package/packages/model-bank/src/aiModels/spark.ts +1 -1
  60. package/packages/model-bank/src/aiModels/stepfun.ts +1 -1
  61. package/packages/model-bank/src/aiModels/taichu.ts +1 -1
  62. package/packages/model-bank/src/aiModels/tencentcloud.ts +1 -1
  63. package/packages/model-bank/src/aiModels/togetherai.ts +1 -1
  64. package/packages/model-bank/src/aiModels/upstage.ts +1 -1
  65. package/packages/model-bank/src/aiModels/v0.ts +1 -1
  66. package/packages/model-bank/src/aiModels/vertexai.ts +3 -3
  67. package/packages/model-bank/src/aiModels/vllm.ts +1 -1
  68. package/packages/model-bank/src/aiModels/volcengine.ts +1 -1
  69. package/packages/model-bank/src/aiModels/wenxin.ts +1 -1
  70. package/packages/model-bank/src/aiModels/xai.ts +1 -1
  71. package/packages/model-bank/src/aiModels/xinference.ts +1 -1
  72. package/packages/model-bank/src/aiModels/zeroone.ts +1 -1
  73. package/packages/model-bank/src/aiModels/zhipu.ts +1 -1
  74. package/packages/model-bank/src/index.ts +1 -0
  75. package/packages/model-bank/src/standard-parameters/index.ts +48 -0
  76. package/packages/{types/src → model-bank/src/types}/aiModel.ts +12 -1
  77. package/packages/model-bank/src/types/index.ts +1 -0
  78. package/packages/model-runtime/package.json +4 -1
  79. package/packages/model-runtime/src/BaseAI.ts +2 -2
  80. package/packages/model-runtime/src/ModelRuntime.test.ts +4 -4
  81. package/packages/model-runtime/src/RouterRuntime/createRuntime.ts +3 -7
  82. package/packages/model-runtime/src/ai302/index.ts +1 -1
  83. package/packages/model-runtime/src/aihubmix/index.ts +1 -2
  84. package/packages/model-runtime/src/anthropic/index.ts +1 -1
  85. package/packages/model-runtime/src/azureOpenai/index.ts +2 -3
  86. package/packages/model-runtime/src/azureai/index.ts +2 -3
  87. package/packages/model-runtime/src/bedrock/index.ts +1 -1
  88. package/packages/model-runtime/src/bfl/createImage.test.ts +4 -4
  89. package/packages/model-runtime/src/bfl/createImage.ts +2 -2
  90. package/packages/model-runtime/src/bfl/index.ts +1 -1
  91. package/packages/model-runtime/src/cloudflare/index.ts +1 -1
  92. package/packages/model-runtime/src/const/models.ts +64 -0
  93. package/packages/model-runtime/src/fal/index.test.ts +2 -3
  94. package/packages/model-runtime/src/fal/index.ts +1 -1
  95. package/packages/model-runtime/src/github/index.ts +1 -1
  96. package/packages/model-runtime/src/google/createImage.test.ts +1 -1
  97. package/packages/model-runtime/src/google/createImage.ts +53 -25
  98. package/packages/model-runtime/src/google/index.test.ts +1 -1
  99. package/packages/model-runtime/src/google/index.ts +4 -3
  100. package/packages/model-runtime/src/groq/index.ts +1 -1
  101. package/packages/model-runtime/src/helpers/parseToolCalls.ts +1 -2
  102. package/packages/model-runtime/src/huggingface/index.ts +1 -1
  103. package/packages/model-runtime/src/index.ts +3 -1
  104. package/packages/model-runtime/src/infiniai/index.ts +1 -1
  105. package/packages/model-runtime/src/ollama/index.test.ts +1 -1
  106. package/packages/model-runtime/src/ollama/index.ts +2 -3
  107. package/packages/model-runtime/src/openai/index.ts +16 -8
  108. package/packages/model-runtime/src/providerTestUtils.ts +1 -2
  109. package/packages/model-runtime/src/qiniu/index.test.ts +2 -3
  110. package/packages/model-runtime/src/qwen/index.ts +1 -1
  111. package/packages/model-runtime/src/siliconcloud/index.ts +2 -2
  112. package/packages/model-runtime/src/types/chat.ts +2 -22
  113. package/packages/model-runtime/src/{error.ts → types/error.ts} +29 -0
  114. package/packages/model-runtime/src/types/index.ts +4 -0
  115. package/packages/model-runtime/src/types/toolsCalling.ts +48 -0
  116. package/packages/model-runtime/src/types/type.ts +1 -1
  117. package/packages/model-runtime/src/types/usage.ts +27 -0
  118. package/packages/model-runtime/src/utils/anthropicHelpers.test.ts +2 -2
  119. package/packages/model-runtime/src/utils/anthropicHelpers.ts +1 -1
  120. package/packages/model-runtime/src/utils/createError.ts +1 -1
  121. package/packages/model-runtime/src/utils/errorResponse.test.ts +110 -0
  122. package/packages/model-runtime/src/utils/errorResponse.ts +64 -0
  123. package/packages/{utils/src → model-runtime/src/utils}/getFallbackModelProperty.ts +1 -1
  124. package/packages/model-runtime/src/utils/googleErrorParser.test.ts +1 -1
  125. package/packages/model-runtime/src/utils/googleErrorParser.ts +1 -1
  126. package/packages/model-runtime/src/utils/handleOpenAIError.ts +1 -1
  127. package/packages/model-runtime/src/utils/imageToBase64.test.ts +91 -0
  128. package/packages/model-runtime/src/utils/imageToBase64.ts +62 -0
  129. package/packages/model-runtime/src/utils/modelParse.test.ts +2 -2
  130. package/packages/model-runtime/src/utils/modelParse.ts +16 -10
  131. package/packages/model-runtime/src/utils/openaiCompatibleFactory/createImage.ts +1 -1
  132. package/packages/model-runtime/src/utils/openaiCompatibleFactory/index.ts +3 -3
  133. package/packages/model-runtime/src/utils/openaiHelpers.test.ts +2 -2
  134. package/packages/model-runtime/src/utils/openaiHelpers.ts +3 -4
  135. package/packages/model-runtime/src/utils/postProcessModelList.ts +2 -2
  136. package/packages/model-runtime/src/utils/safeParseJSON.test.ts +71 -0
  137. package/packages/model-runtime/src/utils/safeParseJSON.ts +12 -0
  138. package/packages/model-runtime/src/utils/streams/bedrock/claude.ts +1 -1
  139. package/packages/model-runtime/src/utils/streams/bedrock/llama.test.ts +1 -2
  140. package/packages/model-runtime/src/utils/streams/bedrock/llama.ts +1 -1
  141. package/packages/model-runtime/src/utils/streams/google-ai.test.ts +1 -1
  142. package/packages/model-runtime/src/utils/streams/google-ai.ts +1 -1
  143. package/packages/model-runtime/src/utils/streams/ollama.test.ts +1 -1
  144. package/packages/model-runtime/src/utils/streams/ollama.ts +2 -3
  145. package/packages/model-runtime/src/utils/streams/openai/openai.test.ts +1 -2
  146. package/packages/model-runtime/src/utils/streams/openai/openai.ts +1 -1
  147. package/packages/model-runtime/src/utils/streams/openai/responsesStream.ts +1 -1
  148. package/packages/model-runtime/src/utils/streams/protocol.ts +3 -3
  149. package/packages/model-runtime/src/utils/streams/vertex-ai.test.ts +1 -1
  150. package/packages/model-runtime/src/utils/streams/vertex-ai.ts +2 -2
  151. package/packages/model-runtime/src/utils/uuid.ts +7 -0
  152. package/packages/model-runtime/src/vertexai/index.ts +1 -1
  153. package/packages/types/src/agent/index.ts +2 -1
  154. package/packages/types/src/aiProvider.ts +10 -2
  155. package/packages/types/src/auth.ts +35 -0
  156. package/packages/types/src/discover/models.ts +1 -1
  157. package/packages/types/src/discover/providers.ts +1 -1
  158. package/packages/types/src/index.ts +4 -0
  159. package/packages/types/src/llm.ts +2 -47
  160. package/packages/types/src/session/agentSession.ts +3 -3
  161. package/packages/types/src/session/index.ts +2 -2
  162. package/packages/types/src/session/sessionGroup.ts +0 -2
  163. package/packages/types/src/user/settings/general.ts +1 -1
  164. package/packages/types/src/user/settings/modelProvider.ts +1 -1
  165. package/packages/utils/src/fetch/fetchSSE.ts +1 -1
  166. package/packages/utils/src/format.ts +2 -3
  167. package/packages/utils/src/index.ts +3 -1
  168. package/packages/utils/src/number.test.ts +1 -2
  169. package/packages/utils/src/number.ts +1 -2
  170. package/packages/utils/src/parseModels.test.ts +1 -2
  171. package/packages/utils/src/parseModels.ts +2 -3
  172. package/packages/utils/src/pricing.test.ts +1 -2
  173. package/packages/utils/src/pricing.ts +1 -1
  174. package/packages/utils/src/server/xor.ts +3 -1
  175. package/src/app/(backend)/middleware/auth/index.ts +1 -2
  176. package/src/app/(backend)/webapi/chat/vertexai/route.ts +1 -1
  177. package/src/app/(backend)/webapi/text-to-image/[provider]/route.ts +1 -2
  178. package/src/app/[variants]/(main)/(mobile)/me/settings/features/useCategory.tsx +2 -16
  179. package/src/app/[variants]/(main)/chat/@session/_layout/Desktop/SessionHeader.tsx +1 -3
  180. package/src/app/[variants]/(main)/chat/@session/_layout/Mobile/SessionHeader.tsx +1 -3
  181. package/src/app/[variants]/(main)/discover/(list)/model/features/List/ModelTypeIcon.tsx +1 -2
  182. package/src/app/[variants]/(main)/image/@menu/components/SeedNumberInput/index.tsx +1 -1
  183. package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/hooks/useAutoDimensions.ts +4 -3
  184. package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +3 -21
  185. package/src/app/[variants]/(main)/settings/provider/features/ModelList/CreateNewModelModal/Form.tsx +1 -1
  186. package/src/app/[variants]/(main)/settings/provider/features/ModelList/ModelItem.tsx +1 -1
  187. package/src/app/[variants]/(main)/settings/provider/features/ModelList/SortModelModal/ListItem.tsx +1 -1
  188. package/src/app/[variants]/(main)/settings/provider/features/ModelList/SortModelModal/index.tsx +1 -1
  189. package/src/components/ModelSelect/index.tsx +1 -1
  190. package/src/config/featureFlags/schema.test.ts +1 -2
  191. package/src/config/featureFlags/schema.ts +0 -6
  192. package/src/config/featureFlags/utils/parser.test.ts +7 -7
  193. package/src/database/_deprecated/core/index.ts +0 -1
  194. package/src/database/_deprecated/core/migrations/migrateSettingsToUser/type.ts +2 -5
  195. package/src/database/_deprecated/core/model.ts +4 -38
  196. package/src/database/_deprecated/models/message.ts +1 -1
  197. package/src/features/Conversation/Extras/Usage/UsageDetail/ModelCard.tsx +1 -1
  198. package/src/features/Conversation/Extras/Usage/UsageDetail/pricing.ts +3 -4
  199. package/src/features/Conversation/Extras/Usage/UsageDetail/tokens.test.ts +1 -1
  200. package/src/features/Conversation/Extras/Usage/UsageDetail/tokens.ts +3 -2
  201. package/src/layout/GlobalProvider/StoreInitialization.tsx +0 -3
  202. package/src/libs/trpc/async/context.ts +2 -1
  203. package/src/libs/trpc/edge/context.ts +2 -6
  204. package/src/libs/trpc/lambda/context.ts +1 -1
  205. package/src/migrations/FromV5ToV6/types/v5.ts +2 -2
  206. package/src/migrations/FromV5ToV6/types/v6.ts +2 -1
  207. package/src/server/globalConfig/genServerAiProviderConfig.ts +3 -3
  208. package/src/server/modules/ModelRuntime/index.test.ts +1 -1
  209. package/src/server/modules/ModelRuntime/index.ts +1 -1
  210. package/src/server/routers/async/caller.ts +2 -1
  211. package/src/server/routers/async/image.ts +2 -2
  212. package/src/server/routers/lambda/aiModel.ts +1 -1
  213. package/src/server/services/chunk/index.ts +2 -1
  214. package/src/server/services/generation/index.ts +2 -2
  215. package/src/services/_auth.ts +2 -1
  216. package/src/services/aiModel/server.test.ts +1 -1
  217. package/src/services/aiModel/type.ts +1 -1
  218. package/src/services/chat.ts +1 -1
  219. package/src/services/upload.ts +3 -3
  220. package/src/store/agent/slices/chat/action.ts +1 -1
  221. package/src/store/aiInfra/slices/aiModel/action.ts +6 -6
  222. package/src/store/aiInfra/slices/aiModel/initialState.ts +1 -1
  223. package/src/store/aiInfra/slices/aiModel/selectors.test.ts +1 -1
  224. package/src/store/aiInfra/slices/aiModel/selectors.ts +2 -1
  225. package/src/store/aiInfra/slices/aiProvider/__tests__/action.test.ts +7 -7
  226. package/src/store/aiInfra/slices/aiProvider/action.ts +8 -8
  227. package/src/store/aiInfra/slices/aiProvider/initialState.ts +2 -1
  228. package/src/store/electron/actions/app.ts +1 -1
  229. package/src/store/image/slices/generationConfig/action.test.ts +1 -1
  230. package/src/store/image/slices/generationConfig/action.ts +1 -1
  231. package/src/store/image/slices/generationConfig/hooks.test.ts +1 -1
  232. package/src/store/image/slices/generationConfig/hooks.ts +6 -3
  233. package/src/store/image/slices/generationConfig/selectors.test.ts +1 -1
  234. package/src/store/serverConfig/selectors.test.ts +0 -1
  235. package/src/store/user/initialState.ts +1 -4
  236. package/src/store/user/selectors.ts +0 -1
  237. package/src/store/user/slices/auth/action.ts +1 -1
  238. package/src/store/user/slices/auth/selectors.ts +3 -4
  239. package/src/store/user/slices/modelList/action.ts +8 -7
  240. package/src/store/user/slices/modelList/selectors/modelProvider.ts +8 -5
  241. package/src/store/user/slices/preference/selectors.ts +3 -2
  242. package/src/store/user/slices/settings/selectors/settings.ts +1 -2
  243. package/src/store/user/store.ts +1 -4
  244. package/docs/self-hosting/advanced/webrtc.mdx +0 -86
  245. package/docs/self-hosting/advanced/webrtc.zh-CN.mdx +0 -80
  246. package/packages/const/src/image.ts +0 -51
  247. package/src/app/[variants]/(main)/settings/sync/features/Alert.tsx +0 -53
  248. package/src/app/[variants]/(main)/settings/sync/features/DeviceInfo/Card.tsx +0 -42
  249. package/src/app/[variants]/(main)/settings/sync/features/DeviceInfo/DeviceName.tsx +0 -62
  250. package/src/app/[variants]/(main)/settings/sync/features/DeviceInfo/SystemIcon.tsx +0 -31
  251. package/src/app/[variants]/(main)/settings/sync/features/DeviceInfo/index.tsx +0 -103
  252. package/src/app/[variants]/(main)/settings/sync/features/WebRTC/ChannelNameInput.tsx +0 -45
  253. package/src/app/[variants]/(main)/settings/sync/features/WebRTC/SyncSwitch/index.css +0 -238
  254. package/src/app/[variants]/(main)/settings/sync/features/WebRTC/SyncSwitch/index.tsx +0 -79
  255. package/src/app/[variants]/(main)/settings/sync/features/WebRTC/generateRandomRoomName.ts +0 -4
  256. package/src/app/[variants]/(main)/settings/sync/features/WebRTC/index.tsx +0 -103
  257. package/src/app/[variants]/(main)/settings/sync/index.tsx +0 -17
  258. package/src/app/[variants]/(main)/settings/sync/page.tsx +0 -29
  259. package/src/database/_deprecated/core/sync.ts +0 -321
  260. package/src/features/SyncStatusInspector/DisableSync.tsx +0 -79
  261. package/src/features/SyncStatusInspector/EnableSync.tsx +0 -132
  262. package/src/features/SyncStatusInspector/EnableTag.tsx +0 -66
  263. package/src/features/SyncStatusInspector/index.tsx +0 -27
  264. package/src/hooks/useSyncData.ts +0 -50
  265. package/src/services/__tests__/sync.test.ts +0 -56
  266. package/src/services/sync.ts +0 -19
  267. package/src/store/user/slices/sync/action.test.ts +0 -164
  268. package/src/store/user/slices/sync/action.ts +0 -101
  269. package/src/store/user/slices/sync/initialState.ts +0 -13
  270. package/src/store/user/slices/sync/selectors.ts +0 -20
  271. /package/packages/{utils/src → model-runtime/src/utils}/getFallbackModelProperty.test.ts +0 -0
@@ -1,66 +0,0 @@
1
- import { Icon, Tag, Tooltip } from '@lobehub/ui';
2
- import { Badge } from 'antd';
3
- import { LucideCloudy, LucideRefreshCw, LucideRouter, LucideWifiOff } from 'lucide-react';
4
- import { memo } from 'react';
5
- import { useTranslation } from 'react-i18next';
6
-
7
- import { PeerSyncStatus } from '@/types/sync';
8
-
9
- const EnableTag = memo<{ isSyncing: boolean; status: PeerSyncStatus }>(({ status, isSyncing }) => {
10
- const { t } = useTranslation('common');
11
-
12
- switch (status) {
13
- case PeerSyncStatus.Connecting: {
14
- return (
15
- <Tag
16
- bordered={false}
17
- color={'blue'}
18
- icon={<Badge color={'blue'} status="processing" />}
19
- style={{ display: 'flex', gap: 4 }}
20
- >
21
- {t('sync.status.connecting')}
22
- </Tag>
23
- );
24
- }
25
-
26
- case PeerSyncStatus.Synced: {
27
- return (
28
- <Tag bordered={false} color={'green'} icon={<Icon icon={LucideCloudy} />}>
29
- {t('sync.status.synced')}
30
- </Tag>
31
- );
32
- }
33
-
34
- case PeerSyncStatus.Ready: {
35
- return (
36
- <Tag bordered={false} color={'blue'} icon={<Icon icon={LucideRouter} />}>
37
- {t('sync.status.ready')}
38
- </Tag>
39
- );
40
- }
41
-
42
- case PeerSyncStatus.Syncing: {
43
- return (
44
- <Tag
45
- bordered={false}
46
- color={'blue'}
47
- icon={<Icon icon={LucideRefreshCw} spin={isSyncing} />}
48
- >
49
- {t('sync.status.syncing')}
50
- </Tag>
51
- );
52
- }
53
-
54
- case PeerSyncStatus.Unconnected: {
55
- return (
56
- <Tooltip title={t('sync.unconnected.tip')}>
57
- <Tag bordered={false} color={'red'} icon={<Icon icon={LucideWifiOff} />}>
58
- {t('sync.status.unconnected')}
59
- </Tag>
60
- </Tooltip>
61
- );
62
- }
63
- }
64
- });
65
-
66
- export default EnableTag;
@@ -1,27 +0,0 @@
1
- import { TooltipPlacement } from 'antd/es/tooltip';
2
- import { memo } from 'react';
3
-
4
- import { useUserStore } from '@/store/user';
5
-
6
- import DisableSync from './DisableSync';
7
- import EnableSync from './EnableSync';
8
-
9
- interface SyncStatusTagProps {
10
- hiddenActions?: boolean;
11
- hiddenEnableGuide?: boolean;
12
- placement?: TooltipPlacement;
13
- }
14
-
15
- const SyncStatusTag = memo<SyncStatusTagProps>(
16
- ({ hiddenActions, placement, hiddenEnableGuide }) => {
17
- const [enableSync] = useUserStore((s) => [s.syncEnabled]);
18
-
19
- return enableSync ? (
20
- <EnableSync hiddenActions={hiddenActions} placement={placement} />
21
- ) : (
22
- <DisableSync noPopover={hiddenEnableGuide} placement={placement} />
23
- );
24
- },
25
- );
26
-
27
- export default SyncStatusTag;
@@ -1,50 +0,0 @@
1
- import { useCallback } from 'react';
2
-
3
- import { useChatStore } from '@/store/chat';
4
- import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
5
- import { useSessionStore } from '@/store/session';
6
- import { useUserStore } from '@/store/user';
7
- import { syncSettingsSelectors, userProfileSelectors } from '@/store/user/selectors';
8
-
9
- export const useSyncEvent = () => {
10
- const [refreshMessages, refreshTopic] = useChatStore((s) => [s.refreshMessages, s.refreshTopic]);
11
- const [refreshSessions] = useSessionStore((s) => [s.refreshSessions]);
12
-
13
- return useCallback((tableKey: string) => {
14
- // console.log('triggerSync Event:', tableKey);
15
-
16
- switch (tableKey) {
17
- case 'messages': {
18
- refreshMessages();
19
- break;
20
- }
21
-
22
- case 'topics': {
23
- refreshTopic();
24
- break;
25
- }
26
-
27
- case 'sessions': {
28
- refreshSessions();
29
- break;
30
- }
31
-
32
- default: {
33
- break;
34
- }
35
- }
36
- }, []);
37
- };
38
-
39
- export const useEnabledDataSync = () => {
40
- const [userId, userEnableSync, useEnabledSync] = useUserStore((s) => [
41
- userProfileSelectors.userId(s),
42
- syncSettingsSelectors.enableWebRTC(s),
43
- s.useEnabledSync,
44
- ]);
45
-
46
- const { enableWebrtc } = useServerConfigStore(featureFlagsSelectors);
47
- const syncEvent = useSyncEvent();
48
-
49
- useEnabledSync(enableWebrtc, { onEvent: syncEvent, userEnableSync, userId });
50
- };
@@ -1,56 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
-
3
- import { dataSync } from '@/database/_deprecated/core';
4
- import { StartDataSyncParams } from '@/types/sync';
5
-
6
- import { syncService } from '../sync';
7
-
8
- vi.mock('@/database/_deprecated/core', () => ({
9
- dataSync: {
10
- startDataSync: vi.fn(),
11
- disconnect: vi.fn(),
12
- },
13
- }));
14
-
15
- describe('SyncService', () => {
16
- afterEach(() => {
17
- vi.resetAllMocks();
18
- });
19
-
20
- describe('enabledSync', () => {
21
- it('should return false when running on server side', async () => {
22
- const params = { user: { id: '123' }, authToken: 'abc' } as unknown as StartDataSyncParams;
23
-
24
- const origin = global.window;
25
-
26
- // @ts-ignore
27
- global.window = undefined;
28
-
29
- const result = await syncService.enabledSync(params);
30
-
31
- expect(result).toBe(false);
32
- expect(dataSync.startDataSync).not.toHaveBeenCalled();
33
-
34
- // reset
35
- global.window = origin;
36
- });
37
-
38
- it('should start data sync and return true when running on client side', async () => {
39
- const params = { user: { id: '123' }, authToken: 'abc' } as unknown as StartDataSyncParams;
40
-
41
- const result = await syncService.enabledSync(params);
42
-
43
- expect(result).toBe(true);
44
- expect(dataSync.startDataSync).toHaveBeenCalledWith(params);
45
- });
46
- });
47
-
48
- describe('disableSync', () => {
49
- it('should disconnect data sync and return false', async () => {
50
- const result = await syncService.disableSync();
51
-
52
- expect(result).toBe(false);
53
- expect(dataSync.disconnect).toHaveBeenCalled();
54
- });
55
- });
56
- });
@@ -1,19 +0,0 @@
1
- import { dataSync } from '@/database/_deprecated/core';
2
- import { StartDataSyncParams } from '@/types/sync';
3
-
4
- class SyncService {
5
- enabledSync = async (params: StartDataSyncParams) => {
6
- if (typeof window === 'undefined') return false;
7
-
8
- await dataSync.startDataSync(params);
9
- return true;
10
- };
11
-
12
- disableSync = async () => {
13
- await dataSync.disconnect();
14
-
15
- return false;
16
- };
17
- }
18
-
19
- export const syncService = new SyncService();
@@ -1,164 +0,0 @@
1
- import { act, renderHook, waitFor } from '@testing-library/react';
2
- import { afterEach, describe, expect, it, vi } from 'vitest';
3
- import { withSWR } from '~test-utils';
4
-
5
- import { syncService } from '@/services/sync';
6
- import { useUserStore } from '@/store/user';
7
- import { userProfileSelectors } from '@/store/user/selectors';
8
- import { syncSettingsSelectors } from '@/store/user/selectors';
9
-
10
- vi.mock('zustand/traditional');
11
-
12
- vi.mock('swr', async (importOriginal) => {
13
- const modules = await importOriginal();
14
- return {
15
- ...(modules as any),
16
- mutate: vi.fn(),
17
- };
18
- });
19
-
20
- afterEach(() => {
21
- vi.restoreAllMocks();
22
- });
23
-
24
- describe('createSyncSlice', () => {
25
- describe('refreshConnection', () => {
26
- it('should not call triggerEnableSync when userId is empty', async () => {
27
- const { result } = renderHook(() => useUserStore());
28
- const onEvent = vi.fn();
29
-
30
- vi.spyOn(userProfileSelectors, 'userId').mockReturnValueOnce(undefined as any);
31
- const triggerEnableSyncSpy = vi.spyOn(result.current, 'triggerEnableSync');
32
-
33
- await act(async () => {
34
- await result.current.refreshConnection(onEvent);
35
- });
36
-
37
- expect(triggerEnableSyncSpy).not.toHaveBeenCalled();
38
- });
39
-
40
- it('should call triggerEnableSync when userId exists', async () => {
41
- const { result } = renderHook(() => useUserStore());
42
- const onEvent = vi.fn();
43
- const userId = 'user-id';
44
-
45
- vi.spyOn(userProfileSelectors, 'userId').mockReturnValueOnce(userId);
46
- const triggerEnableSyncSpy = vi.spyOn(result.current, 'triggerEnableSync');
47
-
48
- await act(async () => {
49
- await result.current.refreshConnection(onEvent);
50
- });
51
-
52
- expect(triggerEnableSyncSpy).toHaveBeenCalledWith(userId, onEvent);
53
- });
54
- });
55
-
56
- describe('triggerEnableSync', () => {
57
- it('should return false when sync.channelName is empty', async () => {
58
- const { result } = renderHook(() => useUserStore());
59
- const userId = 'user-id';
60
- const onEvent = vi.fn();
61
-
62
- vi.spyOn(syncSettingsSelectors, 'webrtcConfig').mockReturnValueOnce({
63
- channelName: '',
64
- enabled: true,
65
- });
66
-
67
- const data = await act(async () => {
68
- return result.current.triggerEnableSync(userId, onEvent);
69
- });
70
-
71
- expect(data).toBe(false);
72
- });
73
-
74
- it('should call globalService.enabledSync when sync.channelName exists', async () => {
75
- const userId = 'user-id';
76
- const onEvent = vi.fn();
77
- const channelName = 'channel-name';
78
- const channelPassword = 'channel-password';
79
- const deviceName = 'device-name';
80
- const signaling = 'signaling';
81
-
82
- vi.spyOn(syncSettingsSelectors, 'webrtcConfig').mockReturnValueOnce({
83
- channelName,
84
- channelPassword,
85
- signaling,
86
- enabled: true,
87
- });
88
- vi.spyOn(syncSettingsSelectors, 'deviceName').mockReturnValueOnce(deviceName);
89
- const enabledSyncSpy = vi.spyOn(syncService, 'enabledSync').mockResolvedValueOnce(true);
90
- const { result } = renderHook(() => useUserStore());
91
-
92
- const data = await act(async () => {
93
- return result.current.triggerEnableSync(userId, onEvent);
94
- });
95
-
96
- expect(enabledSyncSpy).toHaveBeenCalledWith({
97
- channel: { name: channelName, password: channelPassword },
98
- onAwarenessChange: expect.any(Function),
99
- onSyncEvent: onEvent,
100
- onSyncStatusChange: expect.any(Function),
101
- signaling,
102
- user: expect.objectContaining({ id: userId, name: deviceName }),
103
- });
104
- expect(data).toBe(true);
105
- });
106
- });
107
-
108
- describe('useEnabledSync', () => {
109
- it('should return false when userId is empty', async () => {
110
- const { result } = renderHook(
111
- () =>
112
- useUserStore().useEnabledSync(true, {
113
- userEnableSync: true,
114
- userId: undefined,
115
- onEvent: vi.fn(),
116
- }),
117
- {
118
- wrapper: withSWR,
119
- },
120
- );
121
-
122
- await waitFor(() => expect(result.current.data).toBe(false));
123
- });
124
-
125
- it('should call syncService.disableSync when userEnableSync is false', async () => {
126
- const disableSyncSpy = vi.spyOn(syncService, 'disableSync').mockResolvedValueOnce(false);
127
-
128
- const { result } = renderHook(
129
- () =>
130
- useUserStore().useEnabledSync(true, {
131
- userEnableSync: false,
132
- userId: 'user-id',
133
- onEvent: vi.fn(),
134
- }),
135
-
136
- { wrapper: withSWR },
137
- );
138
-
139
- await waitFor(() => expect(result.current.data).toBeUndefined());
140
- expect(disableSyncSpy).toHaveBeenCalled();
141
- });
142
-
143
- it('should call triggerEnableSync when userEnableSync and userId exist', async () => {
144
- const userId = 'user-id';
145
- const onEvent = vi.fn();
146
- const triggerEnableSyncSpy = vi.fn().mockResolvedValueOnce(true);
147
-
148
- const { result } = renderHook(() => useUserStore());
149
-
150
- // replace triggerEnableSync as a mock
151
- result.current.triggerEnableSync = triggerEnableSyncSpy;
152
-
153
- const { result: swrResult } = renderHook(
154
- () => result.current.useEnabledSync(true, { userEnableSync: true, userId, onEvent }),
155
- {
156
- wrapper: withSWR,
157
- },
158
- );
159
-
160
- await waitFor(() => expect(swrResult.current.data).toBe(true));
161
- expect(triggerEnableSyncSpy).toHaveBeenCalledWith(userId, onEvent);
162
- });
163
- });
164
- });
@@ -1,101 +0,0 @@
1
- import useSWR, { SWRResponse } from 'swr';
2
- import type { StateCreator } from 'zustand/vanilla';
3
-
4
- import type { UserStore } from '@/store/user';
5
- import { OnSyncEvent, PeerSyncStatus } from '@/types/sync';
6
- import { browserInfo } from '@/utils/platform';
7
- import { setNamespace } from '@/utils/storeDebug';
8
-
9
- import { userProfileSelectors } from '../auth/selectors';
10
- import { syncSettingsSelectors } from './selectors';
11
-
12
- const n = setNamespace('sync');
13
-
14
- /**
15
- * 设置操作
16
- */
17
- export interface SyncAction {
18
- refreshConnection: (onEvent: OnSyncEvent) => Promise<void>;
19
- triggerEnableSync: (userId: string, onEvent: OnSyncEvent) => Promise<boolean>;
20
- useEnabledSync: (
21
- systemEnable: boolean | undefined,
22
- params: {
23
- onEvent: OnSyncEvent;
24
- userEnableSync: boolean;
25
- userId: string | undefined;
26
- },
27
- ) => SWRResponse;
28
- }
29
-
30
- export const createSyncSlice: StateCreator<
31
- UserStore,
32
- [['zustand/devtools', never]],
33
- [],
34
- SyncAction
35
- > = (set, get) => ({
36
- refreshConnection: async (onEvent) => {
37
- const userId = userProfileSelectors.userId(get());
38
-
39
- if (!userId) return;
40
-
41
- await get().triggerEnableSync(userId, onEvent);
42
- },
43
-
44
- triggerEnableSync: async (userId: string, onEvent: OnSyncEvent) => {
45
- // double-check the sync ability
46
- // if there is no channelName, don't start sync
47
- const sync = syncSettingsSelectors.webrtcConfig(get());
48
- if (!sync.channelName || !sync.signaling) return false;
49
-
50
- const name = syncSettingsSelectors.deviceName(get());
51
-
52
- const defaultUserName = `My ${browserInfo.browser} (${browserInfo.os})`;
53
-
54
- set({ syncStatus: PeerSyncStatus.Connecting });
55
- const { syncService } = await import('@/services/sync');
56
-
57
- return syncService.enabledSync({
58
- channel: {
59
- name: sync.channelName,
60
- password: sync.channelPassword,
61
- },
62
- onAwarenessChange(state) {
63
- set({ syncAwareness: state });
64
- },
65
- onSyncEvent: onEvent,
66
- onSyncStatusChange: (status) => {
67
- set({ syncStatus: status });
68
- },
69
- signaling: sync.signaling,
70
- user: {
71
- id: userId,
72
- // if user don't set the name, use default name
73
- name: name || defaultUserName,
74
- ...browserInfo,
75
- },
76
- });
77
- },
78
-
79
- useEnabledSync: (systemEnable, { userEnableSync, userId, onEvent }) =>
80
- useSWR<boolean>(
81
- systemEnable ? ['enableSync', userEnableSync, userId] : null,
82
- async () => {
83
- // if user don't enable sync or no userId ,don't start sync
84
- if (!userId) return false;
85
-
86
- // if user don't enable sync, stop sync
87
- if (!userEnableSync) {
88
- const { syncService } = await import('@/services/sync');
89
- return syncService.disableSync();
90
- }
91
-
92
- return get().triggerEnableSync(userId, onEvent);
93
- },
94
- {
95
- onSuccess: (syncEnabled) => {
96
- set({ syncEnabled }, false, n('useEnabledSync'));
97
- },
98
- revalidateOnFocus: false,
99
- },
100
- ),
101
- });
@@ -1,13 +0,0 @@
1
- import { PeerSyncStatus, SyncAwarenessState } from '@/types/sync';
2
-
3
- export interface UserSyncState {
4
- syncAwareness: SyncAwarenessState[];
5
- syncEnabled: boolean;
6
- syncStatus: PeerSyncStatus;
7
- }
8
-
9
- export const initialSyncState: UserSyncState = {
10
- syncAwareness: [],
11
- syncEnabled: false,
12
- syncStatus: PeerSyncStatus.Disabled,
13
- };
@@ -1,20 +0,0 @@
1
- import { DEFAULT_SYNC_CONFIG } from '@/const/settings/sync';
2
- import { UserSyncSettings } from '@/types/user/settings';
3
-
4
- import { UserStore } from '../../store';
5
- import { currentSettings } from '../settings/selectors/settings';
6
-
7
- const syncConfig = (s: UserStore): UserSyncSettings =>
8
- currentSettings(s).sync || DEFAULT_SYNC_CONFIG;
9
-
10
- const webrtcConfig = (s: UserStore) => syncConfig(s).webrtc;
11
- const webrtcChannelName = (s: UserStore) => webrtcConfig(s).channelName;
12
- const enableWebRTC = (s: UserStore) => webrtcConfig(s).enabled;
13
- const deviceName = (s: UserStore) => syncConfig(s).deviceName;
14
-
15
- export const syncSettingsSelectors = {
16
- deviceName,
17
- enableWebRTC,
18
- webrtcChannelName,
19
- webrtcConfig,
20
- };