@lobehub/chat 1.140.0 → 1.141.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 (125) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/changelog/v1.json +24 -0
  3. package/locales/ar/chat.json +13 -0
  4. package/locales/ar/common.json +1 -0
  5. package/locales/ar/components.json +4 -0
  6. package/locales/ar/file.json +2 -2
  7. package/locales/bg-BG/chat.json +13 -0
  8. package/locales/bg-BG/common.json +1 -0
  9. package/locales/bg-BG/components.json +4 -0
  10. package/locales/bg-BG/file.json +2 -2
  11. package/locales/de-DE/chat.json +13 -0
  12. package/locales/de-DE/common.json +1 -0
  13. package/locales/de-DE/components.json +4 -0
  14. package/locales/de-DE/file.json +2 -2
  15. package/locales/en-US/chat.json +13 -0
  16. package/locales/en-US/common.json +1 -0
  17. package/locales/en-US/components.json +4 -0
  18. package/locales/en-US/file.json +2 -2
  19. package/locales/es-ES/chat.json +13 -0
  20. package/locales/es-ES/common.json +1 -0
  21. package/locales/es-ES/components.json +4 -0
  22. package/locales/es-ES/file.json +2 -2
  23. package/locales/fa-IR/chat.json +13 -0
  24. package/locales/fa-IR/common.json +1 -0
  25. package/locales/fa-IR/components.json +4 -0
  26. package/locales/fa-IR/file.json +2 -2
  27. package/locales/fr-FR/chat.json +13 -0
  28. package/locales/fr-FR/common.json +1 -0
  29. package/locales/fr-FR/components.json +4 -0
  30. package/locales/fr-FR/file.json +2 -2
  31. package/locales/it-IT/chat.json +13 -0
  32. package/locales/it-IT/common.json +1 -0
  33. package/locales/it-IT/components.json +4 -0
  34. package/locales/it-IT/file.json +2 -2
  35. package/locales/ja-JP/chat.json +13 -0
  36. package/locales/ja-JP/common.json +1 -0
  37. package/locales/ja-JP/components.json +4 -0
  38. package/locales/ja-JP/file.json +2 -2
  39. package/locales/ko-KR/chat.json +13 -0
  40. package/locales/ko-KR/common.json +1 -0
  41. package/locales/ko-KR/components.json +4 -0
  42. package/locales/ko-KR/file.json +2 -2
  43. package/locales/nl-NL/chat.json +13 -0
  44. package/locales/nl-NL/common.json +1 -0
  45. package/locales/nl-NL/components.json +4 -0
  46. package/locales/nl-NL/file.json +2 -2
  47. package/locales/pl-PL/chat.json +13 -0
  48. package/locales/pl-PL/common.json +1 -0
  49. package/locales/pl-PL/components.json +4 -0
  50. package/locales/pl-PL/file.json +2 -2
  51. package/locales/pt-BR/chat.json +13 -0
  52. package/locales/pt-BR/common.json +1 -0
  53. package/locales/pt-BR/components.json +4 -0
  54. package/locales/pt-BR/file.json +2 -2
  55. package/locales/ru-RU/chat.json +13 -0
  56. package/locales/ru-RU/common.json +1 -0
  57. package/locales/ru-RU/components.json +4 -0
  58. package/locales/ru-RU/file.json +2 -2
  59. package/locales/tr-TR/chat.json +13 -0
  60. package/locales/tr-TR/common.json +1 -0
  61. package/locales/tr-TR/components.json +4 -0
  62. package/locales/tr-TR/file.json +2 -2
  63. package/locales/vi-VN/chat.json +13 -0
  64. package/locales/vi-VN/common.json +1 -0
  65. package/locales/vi-VN/components.json +4 -0
  66. package/locales/vi-VN/file.json +2 -2
  67. package/locales/zh-CN/chat.json +13 -0
  68. package/locales/zh-CN/common.json +1 -0
  69. package/locales/zh-CN/components.json +4 -0
  70. package/locales/zh-CN/file.json +2 -2
  71. package/locales/zh-TW/chat.json +13 -0
  72. package/locales/zh-TW/common.json +1 -0
  73. package/locales/zh-TW/components.json +4 -0
  74. package/locales/zh-TW/file.json +2 -2
  75. package/next.config.ts +5 -6
  76. package/package.json +8 -2
  77. package/packages/context-engine/src/__tests__/pipeline.test.ts +7 -27
  78. package/packages/context-engine/src/pipeline.ts +5 -21
  79. package/packages/context-engine/src/types.ts +2 -2
  80. package/packages/database/src/models/__tests__/message.test.ts +200 -2
  81. package/packages/database/src/models/message.ts +13 -0
  82. package/packages/model-runtime/src/core/openaiCompatibleFactory/index.test.ts +313 -0
  83. package/packages/model-runtime/src/core/openaiCompatibleFactory/index.ts +21 -5
  84. package/packages/model-runtime/src/providers/azureai/index.test.ts +12 -2
  85. package/packages/model-runtime/src/providers/groq/index.test.ts +449 -0
  86. package/packages/model-runtime/src/providers/groq/index.ts +46 -0
  87. package/src/app/[variants]/(main)/_layout/Desktop/SideBar/TopActions.tsx +3 -2
  88. package/src/app/[variants]/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/Tags/index.tsx +1 -1
  89. package/src/app/[variants]/(main)/files/(content)/@menu/features/KnowledgeBase/Item/index.tsx +10 -2
  90. package/src/features/ChatInput/InputEditor/index.tsx +2 -0
  91. package/src/features/Conversation/Messages/User/index.tsx +7 -17
  92. package/src/features/Conversation/components/ChatItem/ShareMessageModal/SharePdf/PdfPreview.tsx +361 -0
  93. package/src/features/Conversation/components/ChatItem/ShareMessageModal/SharePdf/index.tsx +119 -0
  94. package/src/features/Conversation/components/ChatItem/ShareMessageModal/SharePdf/style.ts +63 -0
  95. package/src/features/Conversation/components/ChatItem/ShareMessageModal/SharePdf/template.ts +24 -0
  96. package/src/features/Conversation/components/ChatItem/ShareMessageModal/SharePdf/usePdfGeneration.ts +93 -0
  97. package/src/features/Conversation/components/ShareMessageModal/ShareImage/Preview.tsx +1 -1
  98. package/src/features/Conversation/components/ShareMessageModal/index.tsx +39 -14
  99. package/src/features/FileManager/FileList/MasonryFileItem/MasonryItemWrapper.tsx +44 -0
  100. package/src/features/FileManager/FileList/MasonryFileItem/index.tsx +553 -0
  101. package/src/features/FileManager/FileList/MasonrySkeleton.tsx +57 -0
  102. package/src/features/FileManager/FileList/ToolBar/ViewSwitcher.tsx +45 -0
  103. package/src/features/FileManager/FileList/ToolBar/index.tsx +9 -1
  104. package/src/features/FileManager/FileList/index.tsx +83 -13
  105. package/src/features/FileManager/Header/FilesSearchBar.tsx +7 -2
  106. package/src/features/ShareModal/ShareImage/Preview.tsx +1 -1
  107. package/src/features/ShareModal/SharePdf/PdfPreview.tsx +361 -0
  108. package/src/features/ShareModal/SharePdf/index.tsx +194 -0
  109. package/src/features/ShareModal/SharePdf/usePdfGeneration.ts +90 -0
  110. package/src/features/ShareModal/index.tsx +40 -14
  111. package/src/features/ShareModal/style.ts +8 -5
  112. package/src/helpers/toolEngineering/index.ts +7 -1
  113. package/src/helpers/toolFilters.ts +35 -0
  114. package/src/libs/trpc/client/lambda.ts +7 -1
  115. package/src/locales/default/chat.ts +13 -0
  116. package/src/locales/default/common.ts +1 -0
  117. package/src/locales/default/components.ts +4 -0
  118. package/src/locales/default/file.ts +2 -2
  119. package/src/server/globalConfig/parseSystemAgent.ts +4 -2
  120. package/src/server/routers/lambda/exporter.ts +173 -3
  121. package/src/server/routers/lambda/message.ts +11 -0
  122. package/src/services/chat/contextEngineering.ts +1 -9
  123. package/src/store/agent/slices/chat/selectors/agent.ts +16 -6
  124. package/src/store/global/initialState.ts +2 -0
  125. package/src/store/tool/slices/builtin/selectors.ts +15 -5
@@ -33,6 +33,455 @@ afterEach(() => {
33
33
  });
34
34
 
35
35
  describe('LobeGroq - custom features', () => {
36
+ describe('filterAdvancedFields', () => {
37
+ const filterAdvancedFields = params.generateObject!.handleSchema!;
38
+
39
+ it('should filter out maxItems from schema', () => {
40
+ const schema = {
41
+ items: { type: 'string' },
42
+ maxItems: 5,
43
+ type: 'array',
44
+ };
45
+
46
+ const result = filterAdvancedFields(schema);
47
+
48
+ expect(result).toEqual({
49
+ items: { type: 'string' },
50
+ type: 'array',
51
+ });
52
+ expect(result.maxItems).toBeUndefined();
53
+ });
54
+
55
+ it('should filter out minItems from schema', () => {
56
+ const schema = {
57
+ items: { type: 'string' },
58
+ minItems: 2,
59
+ type: 'array',
60
+ };
61
+
62
+ const result = filterAdvancedFields(schema);
63
+
64
+ expect(result).toEqual({
65
+ items: { type: 'string' },
66
+ type: 'array',
67
+ });
68
+ expect(result.minItems).toBeUndefined();
69
+ });
70
+
71
+ it('should filter out maxLength from schema', () => {
72
+ const schema = {
73
+ maxLength: 100,
74
+ type: 'string',
75
+ };
76
+
77
+ const result = filterAdvancedFields(schema);
78
+
79
+ expect(result).toEqual({
80
+ type: 'string',
81
+ });
82
+ expect(result.maxLength).toBeUndefined();
83
+ });
84
+
85
+ it('should filter out minLength from schema', () => {
86
+ const schema = {
87
+ minLength: 5,
88
+ type: 'string',
89
+ };
90
+
91
+ const result = filterAdvancedFields(schema);
92
+
93
+ expect(result).toEqual({
94
+ type: 'string',
95
+ });
96
+ expect(result.minLength).toBeUndefined();
97
+ });
98
+
99
+ it('should filter out pattern from schema', () => {
100
+ const schema = {
101
+ pattern: '^[a-z]+$',
102
+ type: 'string',
103
+ };
104
+
105
+ const result = filterAdvancedFields(schema);
106
+
107
+ expect(result).toEqual({
108
+ type: 'string',
109
+ });
110
+ expect(result.pattern).toBeUndefined();
111
+ });
112
+
113
+ it('should filter out format from schema', () => {
114
+ const schema = {
115
+ format: 'email',
116
+ type: 'string',
117
+ };
118
+
119
+ const result = filterAdvancedFields(schema);
120
+
121
+ expect(result).toEqual({
122
+ type: 'string',
123
+ });
124
+ expect(result.format).toBeUndefined();
125
+ });
126
+
127
+ it('should filter out uniqueItems from schema', () => {
128
+ const schema = {
129
+ items: { type: 'number' },
130
+ type: 'array',
131
+ uniqueItems: true,
132
+ };
133
+
134
+ const result = filterAdvancedFields(schema);
135
+
136
+ expect(result).toEqual({
137
+ items: { type: 'number' },
138
+ type: 'array',
139
+ });
140
+ expect(result.uniqueItems).toBeUndefined();
141
+ });
142
+
143
+ it('should filter out maxProperties from schema', () => {
144
+ const schema = {
145
+ maxProperties: 10,
146
+ type: 'object',
147
+ };
148
+
149
+ const result = filterAdvancedFields(schema);
150
+
151
+ expect(result).toEqual({
152
+ type: 'object',
153
+ });
154
+ expect(result.maxProperties).toBeUndefined();
155
+ });
156
+
157
+ it('should filter out minProperties from schema', () => {
158
+ const schema = {
159
+ minProperties: 2,
160
+ type: 'object',
161
+ };
162
+
163
+ const result = filterAdvancedFields(schema);
164
+
165
+ expect(result).toEqual({
166
+ type: 'object',
167
+ });
168
+ expect(result.minProperties).toBeUndefined();
169
+ });
170
+
171
+ it('should filter out multipleOf from schema', () => {
172
+ const schema = {
173
+ multipleOf: 5,
174
+ type: 'number',
175
+ };
176
+
177
+ const result = filterAdvancedFields(schema);
178
+
179
+ expect(result).toEqual({
180
+ type: 'number',
181
+ });
182
+ expect(result.multipleOf).toBeUndefined();
183
+ });
184
+
185
+ it('should filter out maximum from schema', () => {
186
+ const schema = {
187
+ maximum: 100,
188
+ type: 'number',
189
+ };
190
+
191
+ const result = filterAdvancedFields(schema);
192
+
193
+ expect(result).toEqual({
194
+ type: 'number',
195
+ });
196
+ expect(result.maximum).toBeUndefined();
197
+ });
198
+
199
+ it('should filter out minimum from schema', () => {
200
+ const schema = {
201
+ minimum: 0,
202
+ type: 'number',
203
+ };
204
+
205
+ const result = filterAdvancedFields(schema);
206
+
207
+ expect(result).toEqual({
208
+ type: 'number',
209
+ });
210
+ expect(result.minimum).toBeUndefined();
211
+ });
212
+
213
+ it('should filter out exclusiveMaximum from schema', () => {
214
+ const schema = {
215
+ exclusiveMaximum: 100,
216
+ type: 'number',
217
+ };
218
+
219
+ const result = filterAdvancedFields(schema);
220
+
221
+ expect(result).toEqual({
222
+ type: 'number',
223
+ });
224
+ expect(result.exclusiveMaximum).toBeUndefined();
225
+ });
226
+
227
+ it('should filter out exclusiveMinimum from schema', () => {
228
+ const schema = {
229
+ exclusiveMinimum: 0,
230
+ type: 'number',
231
+ };
232
+
233
+ const result = filterAdvancedFields(schema);
234
+
235
+ expect(result).toEqual({
236
+ type: 'number',
237
+ });
238
+ expect(result.exclusiveMinimum).toBeUndefined();
239
+ });
240
+
241
+ it('should filter out multiple unsupported properties at once', () => {
242
+ const schema = {
243
+ format: 'email',
244
+ maxLength: 100,
245
+ minLength: 5,
246
+ pattern: '^[a-z]+$',
247
+ type: 'string',
248
+ };
249
+
250
+ const result = filterAdvancedFields(schema);
251
+
252
+ expect(result).toEqual({
253
+ type: 'string',
254
+ });
255
+ expect(result.maxLength).toBeUndefined();
256
+ expect(result.minLength).toBeUndefined();
257
+ expect(result.pattern).toBeUndefined();
258
+ expect(result.format).toBeUndefined();
259
+ });
260
+
261
+ it('should preserve supported properties', () => {
262
+ const schema = {
263
+ description: 'A test field',
264
+ enum: ['a', 'b', 'c'],
265
+ maxLength: 10,
266
+ type: 'string',
267
+ };
268
+
269
+ const result = filterAdvancedFields(schema);
270
+
271
+ expect(result).toEqual({
272
+ description: 'A test field',
273
+ enum: ['a', 'b', 'c'],
274
+ type: 'string',
275
+ });
276
+ });
277
+
278
+ it('should handle nested objects recursively', () => {
279
+ const schema = {
280
+ properties: {
281
+ email: {
282
+ format: 'email',
283
+ maxLength: 100,
284
+ type: 'string',
285
+ },
286
+ name: {
287
+ minLength: 2,
288
+ type: 'string',
289
+ },
290
+ },
291
+ type: 'object',
292
+ };
293
+
294
+ const result = filterAdvancedFields(schema);
295
+
296
+ expect(result).toEqual({
297
+ properties: {
298
+ email: {
299
+ type: 'string',
300
+ },
301
+ name: {
302
+ type: 'string',
303
+ },
304
+ },
305
+ type: 'object',
306
+ });
307
+ });
308
+
309
+ it('should handle deeply nested objects', () => {
310
+ const schema = {
311
+ properties: {
312
+ user: {
313
+ properties: {
314
+ address: {
315
+ maxProperties: 5,
316
+ properties: {
317
+ city: {
318
+ maxLength: 50,
319
+ type: 'string',
320
+ },
321
+ zip: {
322
+ pattern: '^\\d{5}$',
323
+ type: 'string',
324
+ },
325
+ },
326
+ type: 'object',
327
+ },
328
+ name: {
329
+ minLength: 1,
330
+ type: 'string',
331
+ },
332
+ },
333
+ type: 'object',
334
+ },
335
+ },
336
+ type: 'object',
337
+ };
338
+
339
+ const result = filterAdvancedFields(schema);
340
+
341
+ expect(result).toEqual({
342
+ properties: {
343
+ user: {
344
+ properties: {
345
+ address: {
346
+ properties: {
347
+ city: {
348
+ type: 'string',
349
+ },
350
+ zip: {
351
+ type: 'string',
352
+ },
353
+ },
354
+ type: 'object',
355
+ },
356
+ name: {
357
+ type: 'string',
358
+ },
359
+ },
360
+ type: 'object',
361
+ },
362
+ },
363
+ type: 'object',
364
+ });
365
+ });
366
+
367
+ it('should handle arrays in schema', () => {
368
+ const schema = {
369
+ items: {
370
+ maxLength: 50,
371
+ type: 'string',
372
+ },
373
+ maxItems: 10,
374
+ minItems: 1,
375
+ type: 'array',
376
+ uniqueItems: true,
377
+ };
378
+
379
+ const result = filterAdvancedFields(schema);
380
+
381
+ expect(result).toEqual({
382
+ items: {
383
+ type: 'string',
384
+ },
385
+ type: 'array',
386
+ });
387
+ });
388
+
389
+ it('should handle arrays of objects', () => {
390
+ const schema = {
391
+ items: {
392
+ properties: {
393
+ age: {
394
+ maximum: 120,
395
+ minimum: 0,
396
+ type: 'number',
397
+ },
398
+ name: {
399
+ maxLength: 100,
400
+ type: 'string',
401
+ },
402
+ },
403
+ type: 'object',
404
+ },
405
+ type: 'array',
406
+ };
407
+
408
+ const result = filterAdvancedFields(schema);
409
+
410
+ expect(result).toEqual({
411
+ items: {
412
+ properties: {
413
+ age: {
414
+ type: 'number',
415
+ },
416
+ name: {
417
+ type: 'string',
418
+ },
419
+ },
420
+ type: 'object',
421
+ },
422
+ type: 'array',
423
+ });
424
+ });
425
+
426
+ it('should handle null values', () => {
427
+ const result = filterAdvancedFields(null);
428
+ expect(result).toBeNull();
429
+ });
430
+
431
+ it('should handle primitive values', () => {
432
+ expect(filterAdvancedFields('string')).toBe('string');
433
+ expect(filterAdvancedFields(123)).toBe(123);
434
+ expect(filterAdvancedFields(true)).toBe(true);
435
+ });
436
+
437
+ it('should handle empty objects', () => {
438
+ const schema = {};
439
+ const result = filterAdvancedFields(schema);
440
+ expect(result).toEqual({});
441
+ });
442
+
443
+ it('should preserve required and other common fields', () => {
444
+ const schema = {
445
+ additionalProperties: false,
446
+ description: 'A person object',
447
+ maxProperties: 10,
448
+ properties: {
449
+ age: {
450
+ description: 'Person age',
451
+ maximum: 150,
452
+ type: 'number',
453
+ },
454
+ name: {
455
+ description: 'Person name',
456
+ maxLength: 100,
457
+ type: 'string',
458
+ },
459
+ },
460
+ required: ['name', 'age'],
461
+ type: 'object',
462
+ };
463
+
464
+ const result = filterAdvancedFields(schema);
465
+
466
+ expect(result).toEqual({
467
+ additionalProperties: false,
468
+ description: 'A person object',
469
+ properties: {
470
+ age: {
471
+ description: 'Person age',
472
+ type: 'number',
473
+ },
474
+ name: {
475
+ description: 'Person name',
476
+ type: 'string',
477
+ },
478
+ },
479
+ required: ['name', 'age'],
480
+ type: 'object',
481
+ });
482
+ });
483
+ });
484
+
36
485
  describe('Debug Configuration', () => {
37
486
  it('should disable debug by default', () => {
38
487
  delete process.env.DEBUG_GROQ_CHAT_COMPLETION;
@@ -13,6 +13,49 @@ export interface GroqModelCard {
13
13
  id: string;
14
14
  }
15
15
 
16
+ /**
17
+ * Filter out advanced JSON Schema properties that Groq doesn't support
18
+ */
19
+ const filterAdvancedFields = (schema: any): any => {
20
+ if (typeof schema !== 'object' || schema === null) {
21
+ return schema;
22
+ }
23
+
24
+ if (Array.isArray(schema)) {
25
+ return schema.map(filterAdvancedFields);
26
+ }
27
+
28
+ const filtered: any = {};
29
+
30
+ // List of advanced properties to filter out
31
+ const unsupportedProperties = new Set([
32
+ 'maxItems',
33
+ 'minItems',
34
+ 'maxLength',
35
+ 'minLength',
36
+ 'pattern',
37
+ 'format',
38
+ 'uniqueItems',
39
+ 'maxProperties',
40
+ 'minProperties',
41
+ 'multipleOf',
42
+ 'maximum',
43
+ 'minimum',
44
+ 'exclusiveMaximum',
45
+ 'exclusiveMinimum',
46
+ ]);
47
+
48
+ for (const [key, value] of Object.entries(schema)) {
49
+ if (unsupportedProperties.has(key)) {
50
+ continue;
51
+ }
52
+
53
+ filtered[key] = filterAdvancedFields(value);
54
+ }
55
+
56
+ return filtered;
57
+ };
58
+
16
59
  export const params = {
17
60
  baseURL: 'https://api.groq.com/openai/v1',
18
61
  chatCompletion: {
@@ -40,6 +83,9 @@ export const params = {
40
83
  debug: {
41
84
  chatCompletion: () => process.env.DEBUG_GROQ_CHAT_COMPLETION === '1',
42
85
  },
86
+ generateObject: {
87
+ handleSchema: filterAdvancedFields,
88
+ },
43
89
  models: async ({ client }) => {
44
90
  const { LOBE_DEFAULT_MODEL_LIST } = await import('model-bank');
45
91
 
@@ -24,6 +24,7 @@ export interface TopActionProps {
24
24
  tab?: SidebarTabKey;
25
25
  }
26
26
 
27
+ // TODO Change icons
27
28
  const TopActions = memo<TopActionProps>(({ tab, isPinned }) => {
28
29
  const { t } = useTranslation('common');
29
30
  const switchBackToChat = useGlobalStore((s) => s.switchBackToChat);
@@ -66,12 +67,12 @@ const TopActions = memo<TopActionProps>(({ tab, isPinned }) => {
66
67
  />
67
68
  </Link>
68
69
  {enableKnowledgeBase && (
69
- <Link aria-label={t('tab.files')} href={'/files'}>
70
+ <Link aria-label={t('tab.knowledgeBase')} href={'/files'}>
70
71
  <ActionIcon
71
72
  active={isFilesActive}
72
73
  icon={FolderClosed}
73
74
  size={ICON_SIZE}
74
- title={t('tab.files')}
75
+ title={t('tab.knowledgeBase')}
75
76
  tooltipProps={{ placement: 'right' }}
76
77
  />
77
78
  </Link>
@@ -28,7 +28,7 @@ const TitleTags = memo(() => {
28
28
  agentSelectors.isAgentConfigLoading(s),
29
29
  ]);
30
30
 
31
- const plugins = useAgentStore(agentSelectors.currentAgentPlugins, isEqual);
31
+ const plugins = useAgentStore(agentSelectors.displayableAgentPlugins, isEqual);
32
32
  const enabledKnowledge = useAgentStore(agentSelectors.currentEnabledKnowledge, isEqual);
33
33
  const enableHistoryCount = useAgentStore(agentChatConfigSelectors.enableHistoryCount);
34
34
 
@@ -1,8 +1,10 @@
1
1
  import { createStyles } from 'antd-style';
2
2
  import Link from 'next/link';
3
- import { memo, useState } from 'react';
3
+ import React, { memo, useState } from 'react';
4
4
  import { Flexbox } from 'react-layout-kit';
5
5
 
6
+ import { useQueryRoute } from '@/hooks/useQueryRoute';
7
+
6
8
  import Content, { knowledgeItemClass } from './Content';
7
9
 
8
10
  const useStyles = createStyles(({ css, token, isDarkMode }) => ({
@@ -44,9 +46,15 @@ export interface KnowledgeBaseItemProps {
44
46
  const KnowledgeBaseItem = memo<KnowledgeBaseItemProps>(({ name, active, id }) => {
45
47
  const { styles, cx } = useStyles();
46
48
  const [isHover, setHovering] = useState(false);
49
+ const router = useQueryRoute();
50
+
51
+ const handleClick = (e: React.MouseEvent) => {
52
+ e.preventDefault();
53
+ router.push(`/repos/${id}`);
54
+ };
47
55
 
48
56
  return (
49
- <Link href={`/repos/${id}`}>
57
+ <Link href={`/repos/${id}`} onClick={handleClick}>
50
58
  <Flexbox
51
59
  align={'center'}
52
60
  className={cx(styles.container, knowledgeItemClass, active && styles.active)}
@@ -7,6 +7,7 @@ import {
7
7
  ReactCodePlugin,
8
8
  ReactCodeblockPlugin,
9
9
  ReactHRPlugin,
10
+ ReactLinkHighlightPlugin,
10
11
  ReactListPlugin,
11
12
  ReactMathPlugin,
12
13
  ReactTablePlugin,
@@ -92,6 +93,7 @@ const InputEditor = memo<{ defaultRows?: number }>(({ defaultRows = 2 }) => {
92
93
  ReactCodePlugin,
93
94
  ReactCodeblockPlugin,
94
95
  ReactHRPlugin,
96
+ ReactLinkHighlightPlugin,
95
97
  ReactTablePlugin,
96
98
  Editor.withProps(ReactMathPlugin, {
97
99
  renderComp: expand
@@ -44,18 +44,8 @@ const remarkPlugins = markdownElements
44
44
  .filter(Boolean);
45
45
 
46
46
  const UserMessage = memo<UserMessageProps>((props) => {
47
- const {
48
- id,
49
- ragQuery,
50
- content,
51
- createdAt,
52
- error,
53
- role,
54
- index,
55
- extra,
56
- disableEditing,
57
- targetId,
58
- } = props;
47
+ const { id, ragQuery, content, createdAt, error, role, index, extra, disableEditing, targetId } =
48
+ props;
59
49
 
60
50
  const { t } = useTranslation('chat');
61
51
  const { mobile } = useResponsive();
@@ -71,14 +61,14 @@ const UserMessage = memo<UserMessageProps>((props) => {
71
61
  ]);
72
62
 
73
63
  const loading = isInRAGFlow || generating;
74
-
64
+
75
65
  // Get target name for DM indicator
76
66
  const userName = useUserStore(userProfileSelectors.nickName) || 'User';
77
67
  const agents = useSessionStore(sessionSelectors.currentGroupAgents);
78
-
68
+
79
69
  const dmIndicator = useMemo(() => {
80
70
  if (!targetId) return undefined;
81
-
71
+
82
72
  let targetName = targetId;
83
73
  if (targetId === 'user') {
84
74
  targetName = userName;
@@ -86,7 +76,7 @@ const UserMessage = memo<UserMessageProps>((props) => {
86
76
  const targetAgent = agents?.find((agent) => agent.id === targetId);
87
77
  targetName = targetAgent?.title || targetId;
88
78
  }
89
-
79
+
90
80
  return <Tag>{t('dm.visibleTo', { target: targetName })}</Tag>;
91
81
  }, [targetId, userName, agents, t]);
92
82
 
@@ -167,7 +157,7 @@ const UserMessage = memo<UserMessageProps>((props) => {
167
157
  direction={placement === 'left' ? 'horizontal' : 'horizontal-reverse'}
168
158
  gap={8}
169
159
  >
170
- <Flexbox flex={1} style={{ minWidth: 0 }}>
160
+ <Flexbox flex={1} style={{ maxWidth: '100%', minWidth: 0 }}>
171
161
  <MessageContent
172
162
  editing={editing}
173
163
  id={id}