@lobehub/chat 1.26.11 → 1.26.13

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,56 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.26.13](https://github.com/lobehub/lobe-chat/compare/v1.26.12...v1.26.13)
6
+
7
+ <sup>Released on **2024-10-30**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Fix the artifacts interface not scrolling.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Fix the artifacts interface not scrolling, closes [#4499](https://github.com/lobehub/lobe-chat/issues/4499) ([8b6e630](https://github.com/lobehub/lobe-chat/commit/8b6e630))
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
+
30
+ ### [Version 1.26.12](https://github.com/lobehub/lobe-chat/compare/v1.26.11...v1.26.12)
31
+
32
+ <sup>Released on **2024-10-30**</sup>
33
+
34
+ #### 🐛 Bug Fixes
35
+
36
+ - **misc**: Fix file image prompts in client mode.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### What's fixed
44
+
45
+ - **misc**: Fix file image prompts in client mode, closes [#4548](https://github.com/lobehub/lobe-chat/issues/4548) ([1b66639](https://github.com/lobehub/lobe-chat/commit/1b66639))
46
+
47
+ </details>
48
+
49
+ <div align="right">
50
+
51
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
52
+
53
+ </div>
54
+
5
55
  ### [Version 1.26.11](https://github.com/lobehub/lobe-chat/compare/v1.26.10...v1.26.11)
6
56
 
7
57
  <sup>Released on **2024-10-29**</sup>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.26.11",
3
+ "version": "1.26.13",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot 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",
@@ -18,7 +18,7 @@ const Renderer = memo<{ content: string; type?: string }>(({ content, type }) =>
18
18
  }
19
19
 
20
20
  case 'text/markdown': {
21
- return <Markdown>{content}</Markdown>;
21
+ return <Markdown style={{ overflow: 'auto' }}>{content}</Markdown>;
22
22
  }
23
23
 
24
24
  default: {
@@ -26,7 +26,7 @@ const ToolUI = () => {
26
26
 
27
27
  return (
28
28
  <>
29
- <Flexbox flex={1} height={'100%'} paddingInline={12}>
29
+ <Flexbox flex={1} height={'100%'} paddingInline={12} style={{ overflow: 'auto' }}>
30
30
  <ToolRender />
31
31
  </Flexbox>
32
32
  <Footer />
@@ -16,7 +16,7 @@ const Body = ({ children }: PropsWithChildren) => {
16
16
  <Flexbox
17
17
  className={cx(body, 'portal-body')}
18
18
  height={'100%'}
19
- style={{ position: 'relative' }}
19
+ style={{ flex: 1, height: 0, position: 'relative' }}
20
20
  width={'100%'}
21
21
  >
22
22
  {children}
@@ -2,8 +2,10 @@ import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
2
2
  import { act } from '@testing-library/react';
3
3
  import { merge } from 'lodash-es';
4
4
  import OpenAI from 'openai';
5
- import { describe, expect, it, vi } from 'vitest';
5
+ import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
6
6
 
7
+ import { getAppConfig } from '@/config/app';
8
+ import { getServerDBConfig } from '@/config/db';
7
9
  import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
8
10
  import {
9
11
  LobeAnthropicAI,
@@ -53,6 +55,15 @@ vi.mock('@/utils/fetch', async (importOriginal) => {
53
55
  return { ...(module as any), getMessageError: vi.fn() };
54
56
  });
55
57
 
58
+ beforeEach(() => {
59
+ // 清除所有模块的缓存
60
+ vi.resetModules();
61
+ // 默认设置 isServerMode 为 false
62
+ vi.mock('@/const/version', () => ({
63
+ isServerMode: false,
64
+ }));
65
+ });
66
+
56
67
  // mock auth
57
68
  vi.mock('../_auth', () => ({
58
69
  createHeaderWithAuth: vi.fn().mockResolvedValue({}),
@@ -126,92 +137,6 @@ describe('ChatService', () => {
126
137
  );
127
138
  });
128
139
 
129
- describe('handle with files content', () => {
130
- it('should includes files', async () => {
131
- const messages = [
132
- {
133
- content: 'Hello',
134
- role: 'user',
135
- imageList: [
136
- {
137
- id: 'imagecx1',
138
- url: 'http://example.com/xxx0asd-dsd.png',
139
- alt: 'ttt.png',
140
- },
141
- ],
142
- fileList: [
143
- {
144
- fileType: 'plain/txt',
145
- size: 100000,
146
- id: 'file1',
147
- url: 'http://abc.com/abc.txt',
148
- name: 'abc.png',
149
- },
150
- {
151
- id: 'file_oKMve9qySLMI',
152
- name: '2402.16667v1.pdf',
153
- type: 'application/pdf',
154
- size: 11256078,
155
- url: 'https://xxx.com/ppp/480497/5826c2b8-fde0-4de1-a54b-a224d5e3d898.pdf',
156
- },
157
- ],
158
- }, // Message with files
159
- { content: 'Hi', role: 'tool', plugin: { identifier: 'plugin1', apiName: 'api1' } }, // Message with tool role
160
- { content: 'Hey', role: 'assistant' }, // Regular user message
161
- ] as ChatMessage[];
162
-
163
- const getChatCompletionSpy = vi.spyOn(chatService, 'getChatCompletion');
164
- await chatService.createAssistantMessage({
165
- messages,
166
- plugins: [],
167
- model: 'gpt-4o',
168
- });
169
-
170
- expect(getChatCompletionSpy).toHaveBeenCalledWith(
171
- {
172
- messages: [
173
- {
174
- content: [
175
- {
176
- text: `Hello
177
-
178
- <files_info>
179
- <images>
180
- <images_docstring>here are user upload images you can refer to</images_docstring>
181
- <image name="ttt.png" url="http://example.com/xxx0asd-dsd.png"></image>
182
- </images>
183
- <files>
184
- <files_docstring>here are user upload files you can refer to</files_docstring>
185
- <file id="file1" name="abc.png" type="plain/txt" size="100000" url="http://abc.com/abc.txt"></file>
186
- <file id="file_oKMve9qySLMI" name="2402.16667v1.pdf" type="undefined" size="11256078" url="https://xxx.com/ppp/480497/5826c2b8-fde0-4de1-a54b-a224d5e3d898.pdf"></file>
187
- </files>
188
- </files_info>`,
189
- type: 'text',
190
- },
191
- {
192
- image_url: { detail: 'auto', url: 'http://example.com/xxx0asd-dsd.png' },
193
- type: 'image_url',
194
- },
195
- ],
196
- role: 'user',
197
- },
198
- {
199
- content: 'Hi',
200
- name: 'plugin1____api1',
201
- role: 'tool',
202
- },
203
- {
204
- content: 'Hey',
205
- role: 'assistant',
206
- },
207
- ],
208
- model: 'gpt-4o',
209
- },
210
- undefined,
211
- );
212
- });
213
- });
214
-
215
140
  describe('should handle content correctly for vision models', () => {
216
141
  it('should include image content when with vision model', async () => {
217
142
  const messages = [
@@ -243,15 +168,7 @@ describe('ChatService', () => {
243
168
  {
244
169
  content: [
245
170
  {
246
- text: `Hello
247
-
248
- <files_info>
249
- <images>
250
- <images_docstring>here are user upload images you can refer to</images_docstring>
251
- <image name="abc.png" url="http://example.com/image.jpg"></image>
252
- </images>
253
-
254
- </files_info>`,
171
+ text: 'Hello',
255
172
  type: 'text',
256
173
  },
257
174
  {
@@ -829,6 +746,163 @@ describe('ChatService', () => {
829
746
  },
830
747
  ]);
831
748
  });
749
+
750
+ describe('handle with files content in server mode', () => {
751
+ it('should includes files', async () => {
752
+ // 重新模拟模块,设置 isServerMode 为 true
753
+ vi.doMock('@/const/version', () => ({
754
+ isServerMode: true,
755
+ }));
756
+
757
+ // 需要在修改模拟后重新导入相关模块
758
+ const { chatService } = await import('../chat');
759
+
760
+ const messages = [
761
+ {
762
+ content: 'Hello',
763
+ role: 'user',
764
+ imageList: [
765
+ {
766
+ id: 'imagecx1',
767
+ url: 'http://example.com/xxx0asd-dsd.png',
768
+ alt: 'ttt.png',
769
+ },
770
+ ],
771
+ fileList: [
772
+ {
773
+ fileType: 'plain/txt',
774
+ size: 100000,
775
+ id: 'file1',
776
+ url: 'http://abc.com/abc.txt',
777
+ name: 'abc.png',
778
+ },
779
+ {
780
+ id: 'file_oKMve9qySLMI',
781
+ name: '2402.16667v1.pdf',
782
+ type: 'application/pdf',
783
+ size: 11256078,
784
+ url: 'https://xxx.com/ppp/480497/5826c2b8-fde0-4de1-a54b-a224d5e3d898.pdf',
785
+ },
786
+ ],
787
+ }, // Message with files
788
+ { content: 'Hi', role: 'tool', plugin: { identifier: 'plugin1', apiName: 'api1' } }, // Message with tool role
789
+ { content: 'Hey', role: 'assistant' }, // Regular user message
790
+ ] as ChatMessage[];
791
+
792
+ const output = chatService['processMessages']({
793
+ messages,
794
+ model: 'gpt-4o',
795
+ });
796
+
797
+ expect(output).toEqual([
798
+ {
799
+ content: [
800
+ {
801
+ text: `Hello
802
+
803
+ <files_info>
804
+ <images>
805
+ <images_docstring>here are user upload images you can refer to</images_docstring>
806
+ <image name="ttt.png" url="http://example.com/xxx0asd-dsd.png"></image>
807
+ </images>
808
+ <files>
809
+ <files_docstring>here are user upload files you can refer to</files_docstring>
810
+ <file id="file1" name="abc.png" type="plain/txt" size="100000" url="http://abc.com/abc.txt"></file>
811
+ <file id="file_oKMve9qySLMI" name="2402.16667v1.pdf" type="undefined" size="11256078" url="https://xxx.com/ppp/480497/5826c2b8-fde0-4de1-a54b-a224d5e3d898.pdf"></file>
812
+ </files>
813
+ </files_info>`,
814
+ type: 'text',
815
+ },
816
+ {
817
+ image_url: { detail: 'auto', url: 'http://example.com/xxx0asd-dsd.png' },
818
+ type: 'image_url',
819
+ },
820
+ ],
821
+ role: 'user',
822
+ },
823
+ {
824
+ content: 'Hi',
825
+ name: 'plugin1____api1',
826
+ role: 'tool',
827
+ },
828
+ {
829
+ content: 'Hey',
830
+ role: 'assistant',
831
+ },
832
+ ]);
833
+ });
834
+ });
835
+
836
+ it('should include image files in server mode', async () => {
837
+ // 重新模拟模块,设置 isServerMode 为 true
838
+ vi.doMock('@/const/version', () => ({
839
+ isServerMode: true,
840
+ }));
841
+
842
+ // 需要在修改模拟后重新导入相关模块
843
+ const { chatService } = await import('../chat');
844
+ const messages = [
845
+ {
846
+ content: 'Hello',
847
+ role: 'user',
848
+ imageList: [
849
+ {
850
+ id: 'file1',
851
+ url: 'http://example.com/image.jpg',
852
+ alt: 'abc.png',
853
+ },
854
+ ],
855
+ }, // Message with files
856
+ { content: 'Hi', role: 'tool', plugin: { identifier: 'plugin1', apiName: 'api1' } }, // Message with tool role
857
+ { content: 'Hey', role: 'assistant' }, // Regular user message
858
+ ] as ChatMessage[];
859
+
860
+ const getChatCompletionSpy = vi.spyOn(chatService, 'getChatCompletion');
861
+ await chatService.createAssistantMessage({
862
+ messages,
863
+ plugins: [],
864
+ model: 'gpt-4-vision-preview',
865
+ });
866
+
867
+ expect(getChatCompletionSpy).toHaveBeenCalledWith(
868
+ {
869
+ messages: [
870
+ {
871
+ content: [
872
+ {
873
+ text: `Hello
874
+
875
+ <files_info>
876
+ <images>
877
+ <images_docstring>here are user upload images you can refer to</images_docstring>
878
+ <image name="abc.png" url="http://example.com/image.jpg"></image>
879
+ </images>
880
+
881
+ </files_info>`,
882
+ type: 'text',
883
+ },
884
+ {
885
+ image_url: { detail: 'auto', url: 'http://example.com/image.jpg' },
886
+ type: 'image_url',
887
+ },
888
+ ],
889
+ role: 'user',
890
+ },
891
+ {
892
+ content: 'Hi',
893
+ name: 'plugin1____api1',
894
+ role: 'tool',
895
+ },
896
+ {
897
+ content: 'Hey',
898
+ role: 'assistant',
899
+ },
900
+ ],
901
+ model: 'gpt-4-vision-preview',
902
+ },
903
+ undefined,
904
+ );
905
+ });
832
906
  });
833
907
  });
834
908
 
@@ -7,6 +7,7 @@ import { INBOX_GUIDE_SYSTEMROLE } from '@/const/guide';
7
7
  import { INBOX_SESSION_ID } from '@/const/session';
8
8
  import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
9
9
  import { TracePayload, TraceTagMap } from '@/const/trace';
10
+ import { isServerMode } from '@/const/version';
10
11
  import { AgentRuntime, ChatCompletionErrorPayload, ModelProvider } from '@/libs/agent-runtime';
11
12
  import { filesPrompts } from '@/prompts/files';
12
13
  import { useSessionStore } from '@/store/session';
@@ -420,7 +421,7 @@ class ChatService {
420
421
 
421
422
  const imageList = m.imageList || [];
422
423
 
423
- const filesContext = filesPrompts({ fileList: m.fileList, imageList });
424
+ const filesContext = isServerMode ? filesPrompts({ fileList: m.fileList, imageList }) : '';
424
425
  return [
425
426
  { text: (m.content + '\n\n' + filesContext).trim(), type: 'text' },
426
427
  ...imageList.map(