@lobehub/chat 1.131.4 → 1.132.1

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 (39) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v1.json +18 -0
  3. package/package.json +1 -1
  4. package/packages/context-engine/src/processors/MessageContent.ts +45 -10
  5. package/packages/context-engine/src/processors/__tests__/MessageContent.test.ts +179 -1
  6. package/packages/database/src/models/message.ts +9 -1
  7. package/packages/model-bank/src/aiModels/google.ts +7 -0
  8. package/packages/model-runtime/src/providers/google/index.ts +31 -8
  9. package/packages/model-runtime/src/types/chat.ts +6 -0
  10. package/packages/prompts/src/prompts/files/index.test.ts +148 -3
  11. package/packages/prompts/src/prompts/files/index.ts +17 -5
  12. package/packages/prompts/src/prompts/files/video.ts +17 -0
  13. package/packages/types/src/agent/index.ts +1 -1
  14. package/packages/types/src/message/chat.ts +2 -4
  15. package/packages/types/src/message/index.ts +1 -0
  16. package/packages/types/src/message/video.ts +5 -0
  17. package/packages/utils/src/client/index.ts +1 -0
  18. package/packages/utils/src/client/videoValidation.test.ts +53 -0
  19. package/packages/utils/src/client/videoValidation.ts +21 -0
  20. package/packages/utils/src/parseModels.ts +4 -0
  21. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/useSend.ts +9 -4
  22. package/src/components/ModelSelect/index.tsx +14 -2
  23. package/src/features/ChatInput/ActionBar/Upload/ClientMode.tsx +7 -0
  24. package/src/features/ChatInput/ActionBar/Upload/ServerMode.tsx +29 -3
  25. package/src/features/ChatInput/components/UploadDetail/UploadStatus.tsx +1 -1
  26. package/src/features/Conversation/Messages/Assistant/index.tsx +4 -1
  27. package/src/features/Conversation/Messages/User/VideoFileListViewer.tsx +31 -0
  28. package/src/features/Conversation/Messages/User/index.tsx +3 -1
  29. package/src/hooks/useModelSupportVideo.ts +10 -0
  30. package/src/locales/default/chat.ts +4 -0
  31. package/src/locales/default/components.ts +1 -0
  32. package/src/server/routers/lambda/aiChat.ts +1 -0
  33. package/src/services/chat/contextEngineering.test.ts +0 -1
  34. package/src/services/chat/contextEngineering.ts +3 -1
  35. package/src/services/chat/helper.ts +4 -0
  36. package/src/services/upload.ts +1 -1
  37. package/src/store/aiInfra/slices/aiModel/selectors.ts +7 -0
  38. package/src/store/chat/slices/aiChat/actions/generateAIChatV2.ts +22 -0
  39. package/src/store/chat/slices/message/action.ts +15 -14
@@ -0,0 +1,10 @@
1
+ import { useAiInfraStore } from '@/store/aiInfra';
2
+ import { aiModelSelectors } from '@/store/aiInfra/selectors';
3
+
4
+ export const useModelSupportVideo = (id?: string, provider?: string) => {
5
+ return useAiInfraStore((s) => {
6
+ if (!id || !provider) return false;
7
+
8
+ return aiModelSelectors.isModelSupportVideo(id, provider)(s);
9
+ });
10
+ };
@@ -285,6 +285,7 @@ export default {
285
285
  actionFiletip: '上传文件',
286
286
  actionTooltip: '上传',
287
287
  disabled: '当前模型不支持视觉识别和文件分析,请切换模型后使用',
288
+ fileNotSupported: '浏览器模式下暂不支持上传文件,仅支持图片',
288
289
  visionNotSupported: '当前模型不支持视觉识别,请切换模型后使用',
289
290
  },
290
291
  preview: {
@@ -294,6 +295,9 @@ export default {
294
295
  processing: '文件处理中...',
295
296
  },
296
297
  },
298
+ validation: {
299
+ videoSizeExceeded: '视频文件大小不能超过 20MB,当前文件大小为 {{actualSize}}',
300
+ },
297
301
  },
298
302
  zenMode: '专注模式',
299
303
  };
@@ -116,6 +116,7 @@ export default {
116
116
  reasoning: '该模型支持深度思考',
117
117
  search: '该模型支持联网搜索',
118
118
  tokens: '该模型单个会话最多支持 {{tokens}} Tokens',
119
+ video: '该模型支持视频识别',
119
120
  vision: '该模型支持视觉识别',
120
121
  },
121
122
  removed: '该模型不在列表中,若取消选中将会自动移除',
@@ -55,6 +55,7 @@ export const aiChatRouter = router({
55
55
  const assistantMessageItem = await ctx.messageModel.create({
56
56
  content: LOADING_FLAT,
57
57
  fromModel: input.newAssistantMessage.model,
58
+ fromProvider: input.newAssistantMessage.provider,
58
59
  parentId: messageId,
59
60
  role: 'assistant',
60
61
  sessionId: input.sessionId!,
@@ -162,7 +162,6 @@ describe('contextEngineering', () => {
162
162
  <images_docstring>here are user upload images you can refer to</images_docstring>
163
163
  <image name="abc.png" url="http://example.com/image.jpg"></image>
164
164
  </images>
165
-
166
165
  </files_info>
167
166
  <!-- END SYSTEM CONTEXT -->`,
168
167
  type: 'text',
@@ -23,7 +23,8 @@ import { toolSelectors } from '@/store/tool/selectors';
23
23
  import { VARIABLE_GENERATORS } from '@/utils/client/parserPlaceholder';
24
24
  import { genToolCallingName } from '@/utils/toolCall';
25
25
 
26
- import { isCanUseFC, isCanUseVision } from './helper';
26
+ import { isCanUseFC, isCanUseVideo, isCanUseVision } from './helper';
27
+
27
28
 
28
29
  interface ContextEngineeringContext {
29
30
  enableHistoryCount?: boolean;
@@ -98,6 +99,7 @@ export const contextEngineering = async ({
98
99
  // 8. Message content processing
99
100
  new MessageContentProcessor({
100
101
  fileContext: { enabled: isServerMode, includeFileUrl: !isDesktop },
102
+ isCanUseVideo,
101
103
  isCanUseVision,
102
104
  model,
103
105
  provider,
@@ -23,6 +23,10 @@ export const isCanUseVision = (model: string, provider: string): boolean => {
23
23
  return aiModelSelectors.isModelSupportVision(model, provider)(getAiInfraStoreState());
24
24
  };
25
25
 
26
+ export const isCanUseVideo = (model: string, provider: string): boolean => {
27
+ return aiModelSelectors.isModelSupportVideo(model, provider)(getAiInfraStoreState()) || false;
28
+ };
29
+
26
30
  /**
27
31
  * TODO: we need to update this function to auto find deploymentName with provider setting config
28
32
  */
@@ -84,7 +84,7 @@ class UploadService {
84
84
 
85
85
  // upload to client s3
86
86
  // 客户端上传逻辑
87
- if (!skipCheckFileType && !file.type.startsWith('image')) {
87
+ if (!skipCheckFileType && !file.type.startsWith('image') && !file.type.startsWith('video')) {
88
88
  onNotSupported?.();
89
89
  return { data: undefined as unknown as FileMetadata, success: false };
90
90
  }
@@ -62,6 +62,12 @@ const isModelSupportVision = (id: string, provider: string) => (s: AIProviderSto
62
62
  return model?.abilities?.vision || false;
63
63
  };
64
64
 
65
+ const isModelSupportVideo = (id: string, provider: string) => (s: AIProviderStoreState) => {
66
+ const model = getEnabledModelById(id, provider)(s);
67
+
68
+ return model?.abilities?.video;
69
+ };
70
+
65
71
  const isModelSupportReasoning = (id: string, provider: string) => (s: AIProviderStoreState) => {
66
72
  const model = getEnabledModelById(id, provider)(s);
67
73
 
@@ -136,6 +142,7 @@ export const aiModelSelectors = {
136
142
  isModelSupportFiles,
137
143
  isModelSupportReasoning,
138
144
  isModelSupportToolUse,
145
+ isModelSupportVideo,
139
146
  isModelSupportVision,
140
147
  modelBuiltinSearchImpl,
141
148
  modelContextWindowTokens,
@@ -23,8 +23,11 @@ import { agentChatConfigSelectors, agentSelectors } from '@/store/agent/slices/c
23
23
  import { aiModelSelectors, aiProviderSelectors, getAiInfraStoreState } from '@/store/aiInfra';
24
24
  import { MainSendMessageOperation } from '@/store/chat/slices/aiChat/initialState';
25
25
  import type { ChatStore } from '@/store/chat/store';
26
+ import { getFileStoreState } from '@/store/file/store';
26
27
  import { getSessionStoreState } from '@/store/session';
27
28
  import { WebBrowsingManifest } from '@/tools/web-browsing';
29
+ import { ChatImageItem } from '@/types/message/image';
30
+ import { ChatVideoItem } from '@/types/message/video';
28
31
  import { setNamespace } from '@/utils/storeDebug';
29
32
 
30
33
  import { chatSelectors, topicSelectors } from '../../../selectors';
@@ -107,6 +110,23 @@ export const generateAIChatV2: StateCreator<
107
110
 
108
111
  const messages = chatSelectors.activeBaseChats(get());
109
112
 
113
+ // 构造服务端模式临时消息的本地媒体预览(优先使用 S3 URL)
114
+ const filesInStore = getFileStoreState().chatUploadFileList;
115
+ const tempImages: ChatImageItem[] = filesInStore
116
+ .filter((f) => f.file?.type?.startsWith('image'))
117
+ .map((f) => ({
118
+ id: f.id,
119
+ url: f.fileUrl || f.base64Url || f.previewUrl || '',
120
+ alt: f.file?.name || f.id,
121
+ }));
122
+ const tempVideos: ChatVideoItem[] = filesInStore
123
+ .filter((f) => f.file?.type?.startsWith('video'))
124
+ .map((f) => ({
125
+ id: f.id,
126
+ url: f.fileUrl || f.base64Url || f.previewUrl || '',
127
+ alt: f.file?.name || f.id,
128
+ }));
129
+
110
130
  // use optimistic update to avoid the slow waiting
111
131
  const tempId = get().internal_createTmpMessage({
112
132
  content: message,
@@ -117,6 +137,8 @@ export const generateAIChatV2: StateCreator<
117
137
  // if there is activeTopicId,then add topicId to message
118
138
  topicId: activeTopicId,
119
139
  threadId: activeThreadId,
140
+ imageList: tempImages.length > 0 ? tempImages : undefined,
141
+ videoList: tempVideos.length > 0 ? tempVideos : undefined,
120
142
  });
121
143
  get().internal_toggleMessageLoading(true, tempId);
122
144
 
@@ -1,6 +1,20 @@
1
1
  /* eslint-disable sort-keys-fix/sort-keys-fix, typescript-sort-keys/interface */
2
2
  // Disable the auto sort key eslint rule to make the code more logic and readable
3
- import { ChatErrorType, TraceEventType } from '@lobechat/types';
3
+ import {
4
+ ChatErrorType,
5
+ ChatImageItem,
6
+ ChatMessage,
7
+ ChatMessageError,
8
+ ChatMessagePluginError,
9
+ CreateMessageParams,
10
+ GroundingSearch,
11
+ MessageMetadata,
12
+ MessageToolCall,
13
+ ModelReasoning,
14
+ TraceEventPayloads,
15
+ TraceEventType,
16
+ UpdateMessageRAGParams,
17
+ } from '@lobechat/types';
4
18
  import { copyToClipboard } from '@lobehub/ui';
5
19
  import isEqual from 'fast-deep-equal';
6
20
  import { SWRResponse, mutate } from 'swr';
@@ -12,19 +26,6 @@ import { topicService } from '@/services/topic';
12
26
  import { traceService } from '@/services/trace';
13
27
  import { ChatStore } from '@/store/chat/store';
14
28
  import { messageMapKey } from '@/store/chat/utils/messageMapKey';
15
- import {
16
- ChatMessage,
17
- ChatMessageError,
18
- ChatMessagePluginError,
19
- CreateMessageParams,
20
- MessageMetadata,
21
- MessageToolCall,
22
- ModelReasoning,
23
- } from '@/types/message';
24
- import { ChatImageItem } from '@/types/message/image';
25
- import { UpdateMessageRAGParams } from '@/types/message/rag';
26
- import { GroundingSearch } from '@/types/search';
27
- import { TraceEventPayloads } from '@/types/trace';
28
29
  import { Action, setNamespace } from '@/utils/storeDebug';
29
30
  import { nanoid } from '@/utils/uuid';
30
31