@lobehub/chat 1.116.2 → 1.116.4

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 (81) hide show
  1. package/.github/PULL_REQUEST_TEMPLATE.md +1 -0
  2. package/.github/workflows/release.yml +2 -0
  3. package/.i18nrc.js +1 -1
  4. package/CHANGELOG.md +50 -0
  5. package/apps/desktop/package.json +1 -1
  6. package/changelog/v1.json +18 -0
  7. package/locales/ar/components.json +12 -0
  8. package/locales/bg-BG/components.json +12 -0
  9. package/locales/de-DE/components.json +12 -0
  10. package/locales/en-US/components.json +12 -0
  11. package/locales/es-ES/components.json +12 -0
  12. package/locales/fa-IR/components.json +12 -0
  13. package/locales/fr-FR/components.json +12 -0
  14. package/locales/it-IT/components.json +12 -0
  15. package/locales/ja-JP/components.json +12 -0
  16. package/locales/ko-KR/components.json +12 -0
  17. package/locales/nl-NL/components.json +12 -0
  18. package/locales/pl-PL/components.json +12 -0
  19. package/locales/pt-BR/components.json +12 -0
  20. package/locales/ru-RU/components.json +12 -0
  21. package/locales/tr-TR/components.json +12 -0
  22. package/locales/vi-VN/components.json +12 -0
  23. package/locales/zh-CN/components.json +12 -0
  24. package/locales/zh-TW/components.json +12 -0
  25. package/package.json +5 -5
  26. package/packages/const/src/index.ts +2 -1
  27. package/packages/const/src/meta.ts +3 -2
  28. package/packages/const/src/settings/agent.ts +9 -4
  29. package/packages/const/src/settings/systemAgent.ts +0 -3
  30. package/packages/file-loaders/vitest.config.mts +3 -7
  31. package/packages/model-runtime/vitest.config.mts +3 -0
  32. package/packages/prompts/package.json +0 -1
  33. package/packages/prompts/src/chains/__tests__/abstractChunk.test.ts +52 -0
  34. package/packages/prompts/src/chains/__tests__/answerWithContext.test.ts +100 -0
  35. package/packages/prompts/src/chains/__tests__/rewriteQuery.test.ts +88 -0
  36. package/packages/prompts/src/chains/__tests__/summaryGenerationTitle.test.ts +107 -0
  37. package/packages/prompts/src/chains/abstractChunk.ts +0 -2
  38. package/packages/prompts/src/chains/rewriteQuery.ts +3 -1
  39. package/packages/prompts/src/index.test.ts +41 -0
  40. package/packages/prompts/src/prompts/systemRole/index.test.ts +136 -0
  41. package/packages/prompts/vitest.config.mts +3 -0
  42. package/packages/types/src/index.ts +2 -0
  43. package/packages/utils/package.json +5 -1
  44. package/packages/utils/src/client/index.ts +2 -0
  45. package/packages/utils/src/server/index.ts +5 -0
  46. package/packages/utils/vitest.config.mts +3 -0
  47. package/src/app/(backend)/middleware/auth/index.test.ts +2 -2
  48. package/src/app/(backend)/middleware/auth/index.ts +1 -1
  49. package/src/app/(backend)/oidc/consent/route.ts +1 -2
  50. package/src/app/(backend)/trpc/desktop/[trpc]/route.ts +26 -0
  51. package/src/app/(backend)/trpc/trpc.test.ts +10 -0
  52. package/src/app/(backend)/webapi/chat/[provider]/route.test.ts +2 -2
  53. package/src/app/(backend)/webapi/plugin/gateway/route.ts +1 -1
  54. package/src/app/[variants]/(main)/files/[id]/page.tsx +1 -1
  55. package/src/app/[variants]/(main)/settings/sync/page.tsx +1 -1
  56. package/src/app/[variants]/(main)/settings/system-agent/index.tsx +2 -1
  57. package/src/app/desktop/devtools/page.tsx +89 -0
  58. package/src/app/desktop/layout.tsx +31 -0
  59. package/src/components/HtmlPreview/HtmlPreviewAction.tsx +32 -0
  60. package/src/components/HtmlPreview/PreviewDrawer.tsx +133 -0
  61. package/src/components/HtmlPreview/index.ts +2 -0
  62. package/src/features/Conversation/components/ChatItem/ShareMessageModal/ShareText/index.tsx +1 -1
  63. package/src/features/Conversation/components/ChatItem/index.tsx +23 -0
  64. package/src/features/ShareModal/ShareJSON/index.tsx +2 -2
  65. package/src/features/ShareModal/ShareText/index.tsx +1 -1
  66. package/src/libs/oidc-provider/adapter.ts +1 -1
  67. package/src/libs/trpc/edge/middleware/jwtPayload.test.ts +1 -1
  68. package/src/libs/trpc/edge/middleware/jwtPayload.ts +1 -2
  69. package/src/libs/trpc/lambda/middleware/keyVaults.ts +1 -2
  70. package/src/locales/default/components.ts +12 -0
  71. package/src/middleware.ts +3 -3
  72. package/src/server/routers/tools/search.test.ts +1 -1
  73. package/src/services/config.ts +2 -4
  74. package/src/utils/client/switchLang.ts +1 -1
  75. package/{packages/utils/src → src/utils}/server/pageProps.ts +2 -1
  76. package/tsconfig.json +1 -1
  77. package/vitest.config.mts +1 -0
  78. /package/{packages/const/src → src/const}/locale.ts +0 -0
  79. /package/{packages/utils/src → src/utils}/locale.test.ts +0 -0
  80. /package/{packages/utils/src → src/utils}/locale.ts +0 -0
  81. /package/{packages/utils/src → src/utils}/server/routeVariants.ts +0 -0
@@ -0,0 +1,100 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { chainAnswerWithContext } from '../answerWithContext';
4
+
5
+ describe('chainAnswerWithContext', () => {
6
+ it('should generate correct chat payload with context and knowledge', () => {
7
+ const testParams = {
8
+ context: ['Context passage 1', 'Context passage 2'],
9
+ knowledge: ['AI', 'Machine Learning'],
10
+ question: 'What is artificial intelligence?',
11
+ };
12
+
13
+ const result = chainAnswerWithContext(testParams);
14
+
15
+ expect(result.messages).toHaveLength(1);
16
+ expect(result.messages![0].role).toBe('user');
17
+ expect(result.messages![0].content).toContain('AI/Machine Learning');
18
+ expect(result.messages![0].content).toContain('Context passage 1');
19
+ expect(result.messages![0].content).toContain('Context passage 2');
20
+ expect(result.messages![0].content).toContain('What is artificial intelligence?');
21
+ });
22
+
23
+ it('should handle single knowledge area', () => {
24
+ const testParams = {
25
+ context: ['Single context'],
26
+ knowledge: ['Technology'],
27
+ question: 'How does it work?',
28
+ };
29
+
30
+ const result = chainAnswerWithContext(testParams);
31
+
32
+ expect(result.messages![0].content).toContain('Technology');
33
+ });
34
+
35
+ it('should handle multiple knowledge areas', () => {
36
+ const testParams = {
37
+ context: ['Context'],
38
+ knowledge: ['AI', 'ML', 'NLP', 'Computer Vision'],
39
+ question: 'Tell me about these fields',
40
+ };
41
+
42
+ const result = chainAnswerWithContext(testParams);
43
+
44
+ expect(result.messages![0].content).toContain('AI/ML/NLP/Computer Vision');
45
+ });
46
+
47
+ it('should handle empty context array', () => {
48
+ const testParams = {
49
+ context: [],
50
+ knowledge: ['AI'],
51
+ question: 'What is AI?',
52
+ };
53
+
54
+ const result = chainAnswerWithContext(testParams);
55
+
56
+ expect(result.messages![0].content).toContain('<Context>');
57
+ expect(result.messages![0].content).toContain('</Context>');
58
+ });
59
+
60
+ it('should include proper context formatting', () => {
61
+ const testParams = {
62
+ context: ['First passage', 'Second passage'],
63
+ knowledge: ['Test'],
64
+ question: 'Test question',
65
+ };
66
+
67
+ const result = chainAnswerWithContext(testParams);
68
+
69
+ expect(result.messages![0].content).toContain(
70
+ '<Context>\nFirst passage\nSecond passage\n</Context>',
71
+ );
72
+ });
73
+
74
+ it('should include proper instructions about using passages', () => {
75
+ const testParams = {
76
+ context: ['Context'],
77
+ knowledge: ['Knowledge'],
78
+ question: 'Question',
79
+ };
80
+
81
+ const result = chainAnswerWithContext(testParams);
82
+ const content = result.messages![0].content;
83
+
84
+ expect(content).toContain('passages might not be relevant');
85
+ expect(content).toContain('please only use the passages that are relevant');
86
+ expect(content).toContain('answer using your knowledge');
87
+ });
88
+
89
+ it('should include markdown formatting instruction', () => {
90
+ const testParams = {
91
+ context: ['Context'],
92
+ knowledge: ['Knowledge'],
93
+ question: 'Question',
94
+ };
95
+
96
+ const result = chainAnswerWithContext(testParams);
97
+
98
+ expect(result.messages![0].content).toContain('follow markdown syntax');
99
+ });
100
+ });
@@ -0,0 +1,88 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+
3
+ // Mock DEFAULT_REWRITE_QUERY
4
+
5
+ import { DEFAULT_REWRITE_QUERY, chainRewriteQuery } from '../rewriteQuery';
6
+
7
+ describe('chainRewriteQuery', () => {
8
+ it('should generate correct chat payload with default instruction', () => {
9
+ const query = 'What about the weather?';
10
+ const context = ['Previous message 1', 'Previous message 2'];
11
+
12
+ const result = chainRewriteQuery(query, context);
13
+
14
+ expect(result.messages).toHaveLength(2);
15
+ expect(result.messages![0].role).toBe('system');
16
+ expect(result.messages![1].role).toBe('user');
17
+ expect(result.messages![0].content).toContain(DEFAULT_REWRITE_QUERY);
18
+ expect(result.messages![1].content).toContain(query);
19
+ });
20
+
21
+ it('should include chat history in system message', () => {
22
+ const query = 'Follow up question';
23
+ const context = ['User: Hello', 'Assistant: Hi there'];
24
+
25
+ const result = chainRewriteQuery(query, context);
26
+
27
+ expect(result.messages![0].content).toContain('<chatHistory>');
28
+ expect(result.messages![0].content).toContain('User: Hello');
29
+ expect(result.messages![0].content).toContain('Assistant: Hi there');
30
+ expect(result.messages![0].content).toContain('</chatHistory>');
31
+ });
32
+
33
+ it('should use custom instruction when provided', () => {
34
+ const query = 'Test query';
35
+ const context = ['Context'];
36
+ const customInstruction = 'Custom rewrite instruction';
37
+
38
+ const result = chainRewriteQuery(query, context, customInstruction);
39
+
40
+ expect(result.messages![0].content).toContain(customInstruction);
41
+ expect(result.messages![0].content).not.toContain(DEFAULT_REWRITE_QUERY);
42
+ });
43
+
44
+ it('should format user message correctly', () => {
45
+ const query = 'What is the status?';
46
+ const context = ['Previous context'];
47
+
48
+ const result = chainRewriteQuery(query, context);
49
+
50
+ expect(result.messages![1].content).toBe(`Follow Up Input: ${query}, it's standalone query:`);
51
+ });
52
+
53
+ it('should handle empty context array', () => {
54
+ const query = 'Empty context query';
55
+ const context: string[] = [];
56
+
57
+ const result = chainRewriteQuery(query, context);
58
+
59
+ expect(result.messages![0].content).toContain('<chatHistory>\n\n</chatHistory>');
60
+ });
61
+
62
+ it('should handle single context item', () => {
63
+ const query = 'Single context query';
64
+ const context = ['Only one message'];
65
+
66
+ const result = chainRewriteQuery(query, context);
67
+
68
+ expect(result.messages![0].content).toContain('Only one message');
69
+ });
70
+
71
+ it('should join multiple context items with newlines', () => {
72
+ const query = 'Multi context query';
73
+ const context = ['Message 1', 'Message 2', 'Message 3'];
74
+
75
+ const result = chainRewriteQuery(query, context);
76
+
77
+ expect(result.messages![0].content).toContain('Message 1\nMessage 2\nMessage 3');
78
+ });
79
+
80
+ it('should handle special characters in query', () => {
81
+ const query = 'Query with special chars: @#$%^&*()';
82
+ const context = ['Context'];
83
+
84
+ const result = chainRewriteQuery(query, context);
85
+
86
+ expect(result.messages![1].content).toContain(query);
87
+ });
88
+ });
@@ -0,0 +1,107 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { chainSummaryGenerationTitle } from '../summaryGenerationTitle';
4
+
5
+ describe('chainSummaryGenerationTitle', () => {
6
+ it('should generate correct chat payload for image modal', () => {
7
+ const prompts = ['A beautiful sunset', 'Mountain landscape'];
8
+ const modal = 'image' as const;
9
+ const locale = 'zh-CN';
10
+
11
+ const result = chainSummaryGenerationTitle(prompts, modal, locale);
12
+
13
+ expect(result.messages).toHaveLength(2);
14
+ expect(result.messages![0].role).toBe('system');
15
+ expect(result.messages![1].role).toBe('user');
16
+ expect(result.messages![0].content).toContain('AI image prompt');
17
+ expect(result.messages![0].content).toContain(locale);
18
+ });
19
+
20
+ it('should generate correct chat payload for video modal', () => {
21
+ const prompts = ['Dancing in the rain'];
22
+ const modal = 'video' as const;
23
+ const locale = 'en-US';
24
+
25
+ const result = chainSummaryGenerationTitle(prompts, modal, locale);
26
+
27
+ expect(result.messages![0].content).toContain('AI video prompt');
28
+ expect(result.messages![0].content).toContain(locale);
29
+ });
30
+
31
+ it('should format single prompt correctly', () => {
32
+ const prompts = ['Single prompt'];
33
+ const modal = 'image' as const;
34
+ const locale = 'zh-CN';
35
+
36
+ const result = chainSummaryGenerationTitle(prompts, modal, locale);
37
+
38
+ expect(result.messages![1].content).toContain('1. Single prompt');
39
+ });
40
+
41
+ it('should format multiple prompts with numbering', () => {
42
+ const prompts = ['First prompt', 'Second prompt', 'Third prompt'];
43
+ const modal = 'image' as const;
44
+ const locale = 'zh-CN';
45
+
46
+ const result = chainSummaryGenerationTitle(prompts, modal, locale);
47
+
48
+ const userMessage = result.messages![1].content;
49
+ expect(userMessage).toContain('1. First prompt');
50
+ expect(userMessage).toContain('2. Second prompt');
51
+ expect(userMessage).toContain('3. Third prompt');
52
+ });
53
+
54
+ it('should include system instructions about title requirements', () => {
55
+ const prompts = ['Test prompt'];
56
+ const modal = 'image' as const;
57
+ const locale = 'zh-CN';
58
+
59
+ const result = chainSummaryGenerationTitle(prompts, modal, locale);
60
+
61
+ const systemMessage = result.messages![0].content;
62
+ expect(systemMessage).toContain('资深的 AI 艺术创作者');
63
+ expect(systemMessage).toContain('10个字以内');
64
+ expect(systemMessage).toContain('不需要包含标点符号');
65
+ });
66
+
67
+ it('should handle empty prompts array', () => {
68
+ const prompts: string[] = [];
69
+ const modal = 'image' as const;
70
+ const locale = 'zh-CN';
71
+
72
+ const result = chainSummaryGenerationTitle(prompts, modal, locale);
73
+
74
+ expect(result.messages![1].content).toContain('提示词:\n');
75
+ });
76
+
77
+ it('should handle different locales', () => {
78
+ const prompts = ['Test'];
79
+ const modal = 'image' as const;
80
+ const customLocale = 'ja-JP';
81
+
82
+ const result = chainSummaryGenerationTitle(prompts, modal, customLocale);
83
+
84
+ expect(result.messages![0].content).toContain(customLocale);
85
+ });
86
+
87
+ it('should differentiate between image and video modals in instructions', () => {
88
+ const prompts = ['Test prompt'];
89
+ const locale = 'zh-CN';
90
+
91
+ const imageResult = chainSummaryGenerationTitle(prompts, 'image', locale);
92
+ const videoResult = chainSummaryGenerationTitle(prompts, 'video', locale);
93
+
94
+ expect(imageResult.messages![0].content).toContain('AI image prompt');
95
+ expect(videoResult.messages![0].content).toContain('AI video prompt');
96
+ });
97
+
98
+ it('should format prompts with newlines between them', () => {
99
+ const prompts = ['Prompt one', 'Prompt two'];
100
+ const modal = 'image' as const;
101
+ const locale = 'zh-CN';
102
+
103
+ const result = chainSummaryGenerationTitle(prompts, modal, locale);
104
+
105
+ expect(result.messages![1].content).toContain('1. Prompt one\n2. Prompt two');
106
+ });
107
+ });
@@ -1,4 +1,3 @@
1
- import { DEFAULT_MODEL } from '@lobechat/const';
2
1
  import { ChatStreamPayload } from '@lobechat/types';
3
2
 
4
3
  export const chainAbstractChunkText = (text: string): Partial<ChatStreamPayload> => {
@@ -14,6 +13,5 @@ export const chainAbstractChunkText = (text: string): Partial<ChatStreamPayload>
14
13
  role: 'user',
15
14
  },
16
15
  ],
17
- model: DEFAULT_MODEL,
18
16
  };
19
17
  };
@@ -1,6 +1,8 @@
1
- import { DEFAULT_REWRITE_QUERY } from '@lobechat/const';
2
1
  import { ChatStreamPayload } from '@lobechat/types';
3
2
 
3
+ export const DEFAULT_REWRITE_QUERY =
4
+ 'Given the following conversation and a follow-up question, rephrase the follow up question to be a standalone question, in its original language. Keep as much details as possible from previous messages. Keep entity names and all.';
5
+
4
6
  export const chainRewriteQuery = (
5
7
  query: string,
6
8
  context: string[],
@@ -0,0 +1,41 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+
3
+ import * as chains from './chains';
4
+ import * as mainExports from './index';
5
+ import * as prompts from './prompts';
6
+
7
+ // Mock the problematic dependency
8
+ vi.mock('@/locales/resources', () => ({
9
+ supportLocales: ['en-US', 'zh-CN'],
10
+ }));
11
+
12
+ describe('Main Index Export', () => {
13
+ it('should export all chains', () => {
14
+ expect(mainExports).toEqual(expect.objectContaining(chains));
15
+ });
16
+
17
+ it('should export all prompts', () => {
18
+ expect(mainExports).toEqual(expect.objectContaining(prompts));
19
+ });
20
+
21
+ it('should have all expected chain exports', () => {
22
+ const chainExports = [
23
+ 'chainAbstractChunkText',
24
+ 'chainAnswerWithContext',
25
+ 'chainLangDetect',
26
+ 'chainPickEmoji',
27
+ 'chainRewriteQuery',
28
+ 'chainSummaryAgentName',
29
+ 'chainSummaryDescription',
30
+ 'chainSummaryGenerationTitle',
31
+ 'chainSummaryHistory',
32
+ 'chainSummaryTags',
33
+ 'chainSummaryTitle',
34
+ 'chainTranslate',
35
+ ];
36
+
37
+ chainExports.forEach((exportName) => {
38
+ expect(mainExports).toHaveProperty(exportName);
39
+ });
40
+ });
41
+ });
@@ -0,0 +1,136 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { BuiltinSystemRolePrompts } from './index';
4
+
5
+ describe('BuiltinSystemRolePrompts', () => {
6
+ it('should return welcome message only when only welcome is provided', () => {
7
+ const result = BuiltinSystemRolePrompts({
8
+ welcome: 'Welcome to the assistant!',
9
+ });
10
+
11
+ expect(result).toBe('Welcome to the assistant!');
12
+ });
13
+
14
+ it('should return plugins message only when only plugins is provided', () => {
15
+ const result = BuiltinSystemRolePrompts({
16
+ plugins: 'Available plugins: calculator, weather',
17
+ });
18
+
19
+ expect(result).toBe('Available plugins: calculator, weather');
20
+ });
21
+
22
+ it('should return history summary when only history is provided', () => {
23
+ const result = BuiltinSystemRolePrompts({
24
+ historySummary: 'User discussed AI topics previously',
25
+ });
26
+
27
+ expect(result).toContain('<chat_history_summary>');
28
+ expect(result).toContain(
29
+ '<docstring>Users may have lots of chat messages, here is the summary of the history:</docstring>',
30
+ );
31
+ expect(result).toContain('<summary>User discussed AI topics previously</summary>');
32
+ expect(result).toContain('</chat_history_summary>');
33
+ expect(result.trim()).toMatch(/^<chat_history_summary>[\s\S]*<\/chat_history_summary>$/);
34
+ });
35
+
36
+ it('should combine all three parts when all are provided', () => {
37
+ const result = BuiltinSystemRolePrompts({
38
+ welcome: 'Welcome!',
39
+ plugins: 'Plugins available',
40
+ historySummary: 'Previous conversation summary',
41
+ });
42
+
43
+ expect(result).toContain('Welcome!');
44
+ expect(result).toContain('Plugins available');
45
+ expect(result).toContain('<chat_history_summary>');
46
+ expect(result).toContain('Previous conversation summary');
47
+ expect(result).toContain('</chat_history_summary>');
48
+
49
+ // Should be joined with double newlines
50
+ const parts = result.split('\n\n');
51
+ expect(parts).toHaveLength(3);
52
+ });
53
+
54
+ it('should combine welcome and plugins when no history is provided', () => {
55
+ const result = BuiltinSystemRolePrompts({
56
+ welcome: 'Hello user!',
57
+ plugins: 'Available tools',
58
+ });
59
+
60
+ expect(result).toBe('Hello user!\n\nAvailable tools');
61
+ });
62
+
63
+ it('should combine welcome and history when no plugins provided', () => {
64
+ const result = BuiltinSystemRolePrompts({
65
+ welcome: 'Greetings!',
66
+ historySummary: 'Chat history here',
67
+ });
68
+
69
+ expect(result).toContain('Greetings!');
70
+ expect(result).toContain('<chat_history_summary>');
71
+ expect(result).toContain('Chat history here');
72
+ });
73
+
74
+ it('should combine plugins and history when no welcome provided', () => {
75
+ const result = BuiltinSystemRolePrompts({
76
+ plugins: 'Tool list',
77
+ historySummary: 'Summary of previous chats',
78
+ });
79
+
80
+ expect(result).toContain('Tool list');
81
+ expect(result).toContain('<chat_history_summary>');
82
+ expect(result).toContain('Summary of previous chats');
83
+ });
84
+
85
+ it('should return empty string when no parameters provided', () => {
86
+ const result = BuiltinSystemRolePrompts({});
87
+
88
+ expect(result).toBe('');
89
+ });
90
+
91
+ it('should filter out falsy values', () => {
92
+ const result = BuiltinSystemRolePrompts({
93
+ welcome: '',
94
+ plugins: 'Valid plugins',
95
+ historySummary: undefined,
96
+ });
97
+
98
+ expect(result).toBe('Valid plugins');
99
+ });
100
+
101
+ it('should handle null and undefined values gracefully', () => {
102
+ const result = BuiltinSystemRolePrompts({
103
+ welcome: undefined,
104
+ plugins: null as any,
105
+ historySummary: 'Valid history',
106
+ });
107
+
108
+ expect(result).toContain('<chat_history_summary>');
109
+ expect(result).toContain('<summary>Valid history</summary>');
110
+ expect(result).toContain('</chat_history_summary>');
111
+ });
112
+
113
+ it('should preserve whitespace in individual components', () => {
114
+ const result = BuiltinSystemRolePrompts({
115
+ welcome: 'Welcome\nwith newlines',
116
+ plugins: 'Plugins\twith tabs',
117
+ });
118
+
119
+ expect(result).toContain('Welcome\nwith newlines');
120
+ expect(result).toContain('Plugins\twith tabs');
121
+ });
122
+
123
+ it('should format history summary with proper XML structure', () => {
124
+ const historySummary = 'User asked about weather and traffic';
125
+ const result = BuiltinSystemRolePrompts({
126
+ historySummary,
127
+ });
128
+
129
+ expect(result).toContain('<chat_history_summary>');
130
+ expect(result).toContain(
131
+ '<docstring>Users may have lots of chat messages, here is the summary of the history:</docstring>',
132
+ );
133
+ expect(result).toContain('<summary>User asked about weather and traffic</summary>');
134
+ expect(result).toContain('</chat_history_summary>');
135
+ });
136
+ });
@@ -2,6 +2,9 @@ import { defineConfig } from 'vitest/config';
2
2
 
3
3
  export default defineConfig({
4
4
  test: {
5
+ coverage: {
6
+ reporter: ['text', 'json', 'lcov', 'text-summary'],
7
+ },
5
8
  environment: 'happy-dom',
6
9
  },
7
10
  });
@@ -1,3 +1,4 @@
1
+ export * from './agent';
1
2
  export * from './artifact';
2
3
  export * from './chunk';
3
4
  export * from './clientDB';
@@ -6,6 +7,7 @@ export * from './fetch';
6
7
  export * from './knowledgeBase';
7
8
  export * from './llm';
8
9
  export * from './message';
10
+ export * from './meta';
9
11
  export * from './user';
10
12
  export * from './user/settings';
11
13
  // FIXME: I think we need a refactor for the "openai" types
@@ -2,7 +2,11 @@
2
2
  "name": "@lobechat/utils",
3
3
  "version": "1.0.0",
4
4
  "private": true,
5
- "main": "./src/index.ts",
5
+ "exports": {
6
+ ".": "./src/index.ts",
7
+ "./server": "./src/server/index.ts",
8
+ "./client": "./src/client/index.ts"
9
+ },
6
10
  "scripts": {
7
11
  "test": "vitest",
8
12
  "test:coverage": "vitest --coverage"
@@ -0,0 +1,2 @@
1
+ export * from './downloadFile';
2
+ export * from './exportFile';
@@ -0,0 +1,5 @@
1
+ export * from './auth';
2
+ export * from './correctOIDCUrl';
3
+ export * from './geo';
4
+ export * from './responsive';
5
+ export * from './xor';
@@ -10,6 +10,9 @@ export default defineConfig({
10
10
  '@': resolve(__dirname, '../../src'),
11
11
  /* eslint-enable */
12
12
  },
13
+ coverage: {
14
+ reporter: ['text', 'json', 'lcov', 'text-summary'],
15
+ },
13
16
  environment: 'happy-dom',
14
17
  setupFiles: join(__dirname, './tests/setup.ts'),
15
18
  },
@@ -1,9 +1,9 @@
1
1
  import { AgentRuntimeError } from '@lobechat/model-runtime';
2
2
  import { ChatErrorType } from '@lobechat/types';
3
+ import { getXorPayload } from '@lobechat/utils/server';
3
4
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
5
 
5
6
  import { createErrorResponse } from '@/utils/errorResponse';
6
- import { getXorPayload } from '@/utils/server/xor';
7
7
 
8
8
  import { RequestHandler, checkAuth } from './index';
9
9
  import { checkAuthMethod } from './utils';
@@ -20,7 +20,7 @@ vi.mock('./utils', () => ({
20
20
  checkAuthMethod: vi.fn(),
21
21
  }));
22
22
 
23
- vi.mock('@/utils/server/xor', () => ({
23
+ vi.mock('@lobechat/utils/server', () => ({
24
24
  getXorPayload: vi.fn(),
25
25
  }));
26
26
 
@@ -5,6 +5,7 @@ import {
5
5
  ModelRuntime,
6
6
  } from '@lobechat/model-runtime';
7
7
  import { ChatErrorType } from '@lobechat/types';
8
+ import { getXorPayload } from '@lobechat/utils/server';
8
9
  import { NextRequest } from 'next/server';
9
10
 
10
11
  import {
@@ -17,7 +18,6 @@ import {
17
18
  import { ClerkAuth } from '@/libs/clerk-auth';
18
19
  import { validateOIDCJWT } from '@/libs/oidc-provider/jwt';
19
20
  import { createErrorResponse } from '@/utils/errorResponse';
20
- import { getXorPayload } from '@/utils/server/xor';
21
21
 
22
22
  import { checkAuthMethod } from './utils';
23
23
 
@@ -1,9 +1,8 @@
1
+ import { correctOIDCUrl, getUserAuth } from '@lobechat/utils/server';
1
2
  import debug from 'debug';
2
3
  import { NextRequest, NextResponse } from 'next/server';
3
4
 
4
5
  import { OIDCService } from '@/server/services/oidc';
5
- import { getUserAuth } from '@/utils/server/auth';
6
- import { correctOIDCUrl } from '@/utils/server/correctOIDCUrl';
7
6
 
8
7
  const log = debug('lobe-oidc:consent');
9
8
 
@@ -0,0 +1,26 @@
1
+ import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
2
+ import type { NextRequest } from 'next/server';
3
+
4
+ import { pino } from '@/libs/logger';
5
+ import { createLambdaContext } from '@/libs/trpc/lambda/context';
6
+ import { desktopRouter } from '@/server/routers/desktop';
7
+
8
+ const handler = (req: NextRequest) =>
9
+ fetchRequestHandler({
10
+ /**
11
+ * @link https://trpc.io/docs/v11/context
12
+ */
13
+ createContext: () => createLambdaContext(req),
14
+
15
+ endpoint: '/trpc/desktop',
16
+
17
+ onError: ({ error, path, type }) => {
18
+ pino.info(`Error in tRPC handler (desktop) on path: ${path}, type: ${type}`);
19
+ console.error(error);
20
+ },
21
+
22
+ req,
23
+ router: desktopRouter,
24
+ });
25
+
26
+ export { handler as GET, handler as POST };
@@ -0,0 +1,10 @@
1
+ import { existsSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { describe, expect, it } from 'vitest';
4
+
5
+ describe('Desktop TRPC Route', () => {
6
+ it('should have desktop directory', () => {
7
+ const desktopPath = join(__dirname, 'desktop');
8
+ expect(existsSync(desktopPath)).toBe(true);
9
+ });
10
+ });
@@ -2,11 +2,11 @@
2
2
  import { getAuth } from '@clerk/nextjs/server';
3
3
  import { LobeRuntimeAI, ModelRuntime } from '@lobechat/model-runtime';
4
4
  import { ChatErrorType } from '@lobechat/types';
5
+ import { getXorPayload } from '@lobechat/utils/server';
5
6
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
6
7
 
7
8
  import { checkAuthMethod } from '@/app/(backend)/middleware/auth/utils';
8
9
  import { LOBE_CHAT_AUTH_HEADER, OAUTH_AUTHORIZED } from '@/const/auth';
9
- import { getXorPayload } from '@/utils/server/xor';
10
10
 
11
11
  import { POST } from './route';
12
12
 
@@ -18,7 +18,7 @@ vi.mock('@/app/(backend)/middleware/auth/utils', () => ({
18
18
  checkAuthMethod: vi.fn(),
19
19
  }));
20
20
 
21
- vi.mock('@/utils/server/xor', () => ({
21
+ vi.mock('@lobechat/utils/server', () => ({
22
22
  getXorPayload: vi.fn(),
23
23
  }));
24
24