@lobehub/lobehub 2.0.0-next.344 → 2.0.0-next.346
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/.cursor/rules/i18n.mdc +1 -1
- package/.cursor/rules/modal-imperative.mdc +162 -0
- package/.cursor/rules/rules-index.mdc +1 -0
- package/.env.example +0 -14
- package/.eslintrc.js +8 -1
- package/CHANGELOG.md +66 -0
- package/CLAUDE.md +4 -2
- package/Dockerfile +3 -13
- package/README.md +3 -5
- package/README.zh-CN.md +3 -5
- package/changelog/v1.json +20 -0
- package/docs/self-hosting/advanced/auth/clerk-to-betterauth.mdx +11 -42
- package/docs/self-hosting/advanced/auth/clerk-to-betterauth.zh-CN.mdx +10 -41
- package/e2e/src/support/webServer.ts +2 -0
- package/locales/ar/error.json +0 -4
- package/locales/bg-BG/error.json +0 -4
- package/locales/de-DE/error.json +0 -4
- package/locales/en-US/error.json +0 -4
- package/locales/es-ES/error.json +0 -4
- package/locales/fa-IR/error.json +0 -4
- package/locales/fr-FR/error.json +0 -4
- package/locales/it-IT/error.json +0 -4
- package/locales/ja-JP/error.json +0 -4
- package/locales/ko-KR/error.json +0 -4
- package/locales/nl-NL/error.json +0 -4
- package/locales/pl-PL/error.json +0 -4
- package/locales/pt-BR/error.json +0 -4
- package/locales/ru-RU/error.json +0 -4
- package/locales/tr-TR/error.json +0 -4
- package/locales/vi-VN/error.json +0 -4
- package/locales/zh-CN/error.json +0 -4
- package/locales/zh-TW/error.json +0 -4
- package/package.json +12 -12
- package/packages/builtin-agents/package.json +2 -0
- package/packages/builtin-agents/src/agents/agent-builder/index.ts +4 -2
- package/packages/builtin-agents/src/agents/group-agent-builder/index.ts +4 -2
- package/packages/builtin-agents/src/agents/page-agent/index.ts +5 -2
- package/packages/context-engine/src/engine/messages/MessagesEngine.ts +9 -9
- package/packages/context-engine/src/providers/GroupContextInjector.ts +19 -33
- package/packages/context-engine/src/providers/__tests__/GroupContextInjector.test.ts +79 -43
- package/packages/context-engine/src/providers/__tests__/__snapshots__/GroupContextInjector.test.ts.snap +5 -15
- package/packages/database/src/repositories/userMemory/__tests__/UserMemoryTopicRepository.test.ts +24 -3
- package/packages/file-loaders/package.json +1 -1
- package/packages/file-loaders/src/loadFile.ts +10 -15
- package/packages/file-loaders/src/loaders/index.ts +68 -19
- package/packages/file-loaders/src/loaders/pdf/__snapshots__/index.test.ts.snap +1 -1
- package/packages/file-loaders/test/__snapshots__/loaders.test.ts.snap +1 -1
- package/packages/model-bank/src/modelProviders/comfyui.ts +0 -1
- package/packages/model-bank/src/modelProviders/fal.ts +0 -1
- package/packages/types/src/fetch.ts +1 -2
- package/packages/utils/src/server/__tests__/auth.test.ts +0 -47
- package/packages/utils/src/server/auth.ts +1 -9
- package/pnpm-workspace.yaml +1 -0
- package/scripts/_shared/checkDeprecatedClerkEnv.js +42 -0
- package/scripts/changelogWorkflow/buildStaticChangelog.ts +2 -1
- package/scripts/clerk-to-betterauth/_internal/types.ts +53 -20
- package/scripts/clerk-to-betterauth/export-clerk-users-with-api.ts +43 -36
- package/scripts/countEnWord.ts +1 -1
- package/scripts/electronWorkflow/modifiers/appCode.mts +2 -131
- package/scripts/i18nWorkflow/protectedPatterns.ts +1 -2
- package/scripts/prebuild.mts +10 -8
- package/scripts/serverLauncher/startServer.js +23 -5
- package/src/app/(backend)/middleware/auth/index.test.ts +8 -4
- package/src/app/(backend)/middleware/auth/index.ts +0 -15
- package/src/app/(backend)/middleware/auth/utils.test.ts +0 -28
- package/src/app/(backend)/middleware/auth/utils.ts +2 -17
- package/src/app/(backend)/webapi/chat/[provider]/route.test.ts +3 -51
- package/src/app/(backend)/webapi/models/[provider]/route.test.ts +8 -4
- package/src/app/[variants]/(auth)/next-auth/signin/AuthSignInBox.tsx +7 -6
- package/src/app/[variants]/(auth)/signup/[[...signup]]/page.tsx +1 -16
- package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/index.tsx +1 -1
- package/src/app/[variants]/(main)/home/features/InputArea/SkillInstallBanner.tsx +13 -13
- package/src/app/[variants]/(main)/home/features/RecentPage/Item.tsx +2 -2
- package/src/app/[variants]/(main)/resource/features/store/action.ts +2 -2
- package/src/app/[variants]/(main)/resource/features/store/initialState.ts +2 -2
- package/src/app/[variants]/(main)/resource/store/action.ts +2 -2
- package/src/app/[variants]/(main)/resource/store/initialState.ts +2 -2
- package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +3 -21
- package/src/app/[variants]/(main)/settings/profile/features/AvatarRow.tsx +1 -2
- package/src/app/[variants]/(main)/settings/security/index.tsx +1 -22
- package/src/app/[variants]/(main)/settings/skill/features/KlavisSkillItem.tsx +12 -14
- package/src/app/[variants]/(main)/settings/skill/features/LobehubSkillItem.tsx +8 -14
- package/src/app/[variants]/(main)/settings/skill/index.tsx +7 -5
- package/src/app/[variants]/(mobile)/me/(home)/__tests__/UserBanner.test.tsx +2 -35
- package/src/app/[variants]/(mobile)/me/(home)/__tests__/useCategory.test.tsx +0 -20
- package/src/app/[variants]/(mobile)/me/(home)/features/UserBanner.tsx +1 -2
- package/src/app/[variants]/(mobile)/me/profile/features/Category.tsx +3 -13
- package/src/app/[variants]/(mobile)/settings/_layout/Header.tsx +2 -3
- package/src/app/[variants]/share/t/[id]/_layout/index.tsx +1 -1
- package/src/app/[variants]/share/t/[id]/index.tsx +1 -1
- package/src/app/robots.tsx +1 -1
- package/src/envs/auth.ts +2 -27
- package/src/envs/llm.ts +2 -2
- package/src/features/AgentSetting/AgentPlugin/index.tsx +9 -12
- package/src/features/ChatInput/ActionBar/Tools/index.tsx +7 -5
- package/src/features/ChatMiniMap/utils.ts +1 -1
- package/src/features/CommandMenu/SearchResults.tsx +1 -1
- package/src/features/Conversation/ChatList/components/AutoScroll/DebugInspector.tsx +166 -0
- package/src/features/Conversation/ChatList/components/AutoScroll/index.tsx +86 -0
- package/src/features/Conversation/ChatList/components/VirtualizedList.tsx +11 -17
- package/src/features/Conversation/Messages/AgentCouncil/components/AutoScrollShadow.tsx +25 -14
- package/src/features/Conversation/Messages/AgentCouncil/components/CouncilMember.tsx +1 -1
- package/src/features/FileViewer/Renderer/PDF/index.tsx +5 -8
- package/src/features/IntegrationDetailModal/IntegrationDetailContent.tsx +305 -0
- package/src/features/IntegrationDetailModal/index.tsx +21 -283
- package/src/features/MCPPluginDetail/Deployment/index.tsx +1 -1
- package/src/features/MCPPluginDetail/Schema/Prompts.tsx +1 -1
- package/src/features/MCPPluginDetail/Schema/Tools.tsx +1 -1
- package/src/features/ProfileEditor/AgentTool.tsx +14 -20
- package/src/features/ResourceManager/components/Explorer/ListView/ListItem/index.tsx +0 -8
- package/src/features/ResourceManager/components/Explorer/MasonryView/MasonryFileItem/NoteFileItem.tsx +1 -1
- package/src/features/ResourceManager/index.tsx +1 -1
- package/src/features/ShareModal/SharePdf/PdfPreview.tsx +4 -4
- package/src/features/SkillStore/LobeHubList/index.tsx +50 -87
- package/src/features/SkillStore/Search/index.tsx +1 -1
- package/src/features/SkillStore/{Content.tsx → SkillStoreContent.tsx} +3 -8
- package/src/features/SkillStore/index.tsx +15 -33
- package/src/features/User/UserPanel/PanelContent.tsx +0 -8
- package/src/features/User/__tests__/PanelContent.test.tsx +1 -35
- package/src/features/User/__tests__/UserAvatar.test.tsx +30 -57
- package/src/features/User/__tests__/useMenu.test.tsx +2 -43
- package/src/layout/AuthProvider/index.tsx +0 -5
- package/src/libs/next/config/define-config.ts +20 -15
- package/src/libs/next/proxy/createRouteMatcher.test.ts +121 -0
- package/src/libs/next/proxy/createRouteMatcher.ts +18 -0
- package/src/libs/next/proxy/define-config.ts +4 -53
- package/src/libs/next-auth/adapter/index.ts +1 -2
- package/src/libs/oidc-provider/provider.test.ts +5 -316
- package/src/libs/pdfjs/pdf.worker.ts +1 -0
- package/src/libs/pdfjs/worker.ts +12 -0
- package/src/libs/trpc/lambda/context.test.ts +0 -13
- package/src/libs/trpc/lambda/context.ts +3 -22
- package/src/libs/trpc/middleware/userAuth.ts +2 -4
- package/src/libs/trusted-client/getSessionUser.ts +2 -17
- package/src/locales/default/error.ts +0 -6
- package/src/locales/default/index.ts +0 -2
- package/src/proxy.ts +0 -1
- package/src/server/routers/lambda/__tests__/user.test.ts +0 -71
- package/src/server/routers/lambda/user.ts +6 -63
- package/src/server/services/changelog/index.test.ts +3 -2
- package/src/server/services/changelog/index.ts +1 -1
- package/src/server/services/user/index.ts +0 -83
- package/src/services/chat/index.ts +1 -2
- package/src/services/chat/mecha/agentConfigResolver.test.ts +43 -0
- package/src/services/chat/mecha/agentConfigResolver.ts +3 -1
- package/src/store/chat/slices/aiChat/actions/__tests__/streamingExecutor.test.ts +58 -14
- package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +10 -2
- package/src/store/user/slices/auth/action.test.ts +1 -81
- package/src/store/user/slices/auth/action.ts +3 -28
- package/src/store/user/slices/auth/initialState.ts +1 -18
- package/src/store/user/slices/auth/selectors.test.ts +2 -127
- package/src/store/user/slices/auth/selectors.ts +1 -21
- package/src/utils/errorResponse.ts +1 -4
- package/src/utils/markdownToTxt.ts +20 -0
- package/locales/ar/clerk.json +0 -545
- package/locales/bg-BG/clerk.json +0 -545
- package/locales/de-DE/clerk.json +0 -545
- package/locales/en-US/clerk.json +0 -545
- package/locales/es-ES/clerk.json +0 -545
- package/locales/fa-IR/clerk.json +0 -545
- package/locales/fr-FR/clerk.json +0 -545
- package/locales/it-IT/clerk.json +0 -545
- package/locales/ja-JP/clerk.json +0 -545
- package/locales/ko-KR/clerk.json +0 -545
- package/locales/nl-NL/clerk.json +0 -545
- package/locales/pl-PL/clerk.json +0 -545
- package/locales/pt-BR/clerk.json +0 -545
- package/locales/ru-RU/clerk.json +0 -545
- package/locales/tr-TR/clerk.json +0 -545
- package/locales/vi-VN/clerk.json +0 -545
- package/locales/zh-CN/clerk.json +0 -545
- package/locales/zh-TW/clerk.json +0 -545
- package/src/app/(backend)/api/webhooks/clerk/__tests__/fixtures/createUser.json +0 -73
- package/src/app/(backend)/api/webhooks/clerk/route.ts +0 -95
- package/src/app/(backend)/api/webhooks/clerk/validateRequest.ts +0 -22
- package/src/app/[variants]/(auth)/login/[[...login]]/page.tsx +0 -27
- package/src/app/[variants]/(main)/settings/security/features/ClerkProfile.tsx +0 -67
- package/src/features/Conversation/ChatList/components/AutoScroll.tsx +0 -25
- package/src/layout/AuthProvider/Clerk/UserUpdater.tsx +0 -40
- package/src/layout/AuthProvider/Clerk/index.tsx +0 -54
- package/src/layout/AuthProvider/Clerk/useAppearance.ts +0 -133
- package/src/libs/clerk-auth/index.test.ts +0 -216
- package/src/libs/clerk-auth/index.ts +0 -80
- package/src/locales/default/clerk.ts +0 -677
- package/src/server/services/user/index.test.ts +0 -220
|
@@ -12,7 +12,7 @@ describe('GroupContextInjector', () => {
|
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
describe('Basic Scenarios', () => {
|
|
15
|
-
it('should inject group context
|
|
15
|
+
it('should inject group context before first user message', async () => {
|
|
16
16
|
const injector = new GroupContextInjector({
|
|
17
17
|
currentAgentId: 'agt_editor',
|
|
18
18
|
currentAgentName: 'Editor',
|
|
@@ -35,31 +35,39 @@ describe('GroupContextInjector', () => {
|
|
|
35
35
|
const context = createContext(input);
|
|
36
36
|
const result = await injector.process(context);
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
// System message should be unchanged
|
|
39
|
+
expect(result.messages[0].content).toBe('You are a helpful editor.');
|
|
40
|
+
|
|
41
|
+
// Should have 3 messages now (system, injected, user)
|
|
42
|
+
expect(result.messages).toHaveLength(3);
|
|
39
43
|
|
|
40
|
-
//
|
|
41
|
-
|
|
44
|
+
// Check injected message (second message)
|
|
45
|
+
const injectedContent = result.messages[1].content;
|
|
46
|
+
expect(result.messages[1].role).toBe('user');
|
|
42
47
|
|
|
43
48
|
// Agent identity (plain text, no wrapper)
|
|
44
|
-
expect(
|
|
45
|
-
expect(
|
|
46
|
-
expect(
|
|
47
|
-
expect(
|
|
48
|
-
expect(
|
|
49
|
+
expect(injectedContent).toContain('You are "Editor"');
|
|
50
|
+
expect(injectedContent).toContain('acting as a participant');
|
|
51
|
+
expect(injectedContent).toContain('"Writing Team"');
|
|
52
|
+
expect(injectedContent).toContain('agt_editor');
|
|
53
|
+
expect(injectedContent).not.toContain('<agent_identity>');
|
|
49
54
|
|
|
50
55
|
// Group context section with system prompt
|
|
51
|
-
expect(
|
|
52
|
-
expect(
|
|
56
|
+
expect(injectedContent).toContain('<group_context>');
|
|
57
|
+
expect(injectedContent).toContain('A team for collaborative writing');
|
|
53
58
|
|
|
54
59
|
// Participants section with XML format
|
|
55
|
-
expect(
|
|
56
|
-
expect(
|
|
57
|
-
expect(
|
|
58
|
-
expect(
|
|
60
|
+
expect(injectedContent).toContain('<group_participants>');
|
|
61
|
+
expect(injectedContent).toContain('<member name="Supervisor" id="agt_supervisor" />');
|
|
62
|
+
expect(injectedContent).toContain('<member name="Writer" id="agt_writer" />');
|
|
63
|
+
expect(injectedContent).toContain('<member name="Editor" id="agt_editor" you="true" />');
|
|
59
64
|
|
|
60
65
|
// Identity rules
|
|
61
|
-
expect(
|
|
62
|
-
expect(
|
|
66
|
+
expect(injectedContent).toContain('<identity_rules>');
|
|
67
|
+
expect(injectedContent).toContain('NEVER expose or display agent IDs');
|
|
68
|
+
|
|
69
|
+
// Original user message should be third
|
|
70
|
+
expect(result.messages[2].content).toBe('Please review this.');
|
|
63
71
|
|
|
64
72
|
// Metadata should be updated
|
|
65
73
|
expect(result.metadata.groupContextInjected).toBe(true);
|
|
@@ -72,35 +80,37 @@ describe('GroupContextInjector', () => {
|
|
|
72
80
|
enabled: false, // Disabled
|
|
73
81
|
});
|
|
74
82
|
|
|
75
|
-
const input: any[] = [
|
|
83
|
+
const input: any[] = [
|
|
84
|
+
{ role: 'system', content: 'You are a helpful editor.' },
|
|
85
|
+
{ role: 'user', content: 'Hello' },
|
|
86
|
+
];
|
|
76
87
|
|
|
77
88
|
const context = createContext(input);
|
|
78
89
|
const result = await injector.process(context);
|
|
79
90
|
|
|
80
|
-
// Should be unchanged
|
|
91
|
+
// Should be unchanged - no injection
|
|
92
|
+
expect(result.messages).toHaveLength(2);
|
|
81
93
|
expect(result.messages[0].content).toBe('You are a helpful editor.');
|
|
94
|
+
expect(result.messages[1].content).toBe('Hello');
|
|
82
95
|
expect(result.metadata.groupContextInjected).toBeUndefined();
|
|
83
96
|
});
|
|
84
97
|
|
|
85
|
-
it('should skip injection when no
|
|
98
|
+
it('should skip injection when no user message exists', async () => {
|
|
86
99
|
const injector = new GroupContextInjector({
|
|
87
100
|
currentAgentId: 'agt_editor',
|
|
88
101
|
currentAgentName: 'Editor',
|
|
89
102
|
enabled: true,
|
|
90
103
|
});
|
|
91
104
|
|
|
92
|
-
const input: any[] = [
|
|
93
|
-
{ role: 'user', content: 'Hello' },
|
|
94
|
-
{ role: 'assistant', content: 'Hi there!' },
|
|
95
|
-
];
|
|
105
|
+
const input: any[] = [{ role: 'system', content: 'You are a helpful editor.' }];
|
|
96
106
|
|
|
97
107
|
const context = createContext(input);
|
|
98
108
|
const result = await injector.process(context);
|
|
99
109
|
|
|
100
|
-
// Messages should be unchanged
|
|
101
|
-
expect(result.messages
|
|
102
|
-
expect(result.messages[
|
|
103
|
-
expect(result.metadata.groupContextInjected).
|
|
110
|
+
// Messages should be unchanged - no user message to inject before
|
|
111
|
+
expect(result.messages).toHaveLength(1);
|
|
112
|
+
expect(result.messages[0].content).toBe('You are a helpful editor.');
|
|
113
|
+
expect(result.metadata.groupContextInjected).toBe(true);
|
|
104
114
|
});
|
|
105
115
|
});
|
|
106
116
|
|
|
@@ -113,12 +123,16 @@ describe('GroupContextInjector', () => {
|
|
|
113
123
|
enabled: true,
|
|
114
124
|
});
|
|
115
125
|
|
|
116
|
-
const input: any[] = [
|
|
126
|
+
const input: any[] = [
|
|
127
|
+
{ content: 'You are an editor.', role: 'system' },
|
|
128
|
+
{ content: 'Hello', role: 'user' },
|
|
129
|
+
];
|
|
117
130
|
|
|
118
131
|
const context = createContext(input);
|
|
119
132
|
const result = await injector.process(context);
|
|
120
133
|
|
|
121
|
-
|
|
134
|
+
// Check injected message content
|
|
135
|
+
expect(result.messages[1].content).toMatchSnapshot();
|
|
122
136
|
});
|
|
123
137
|
|
|
124
138
|
it('should handle config with only group info', async () => {
|
|
@@ -129,12 +143,16 @@ describe('GroupContextInjector', () => {
|
|
|
129
143
|
systemPrompt: 'Test group description',
|
|
130
144
|
});
|
|
131
145
|
|
|
132
|
-
const input: any[] = [
|
|
146
|
+
const input: any[] = [
|
|
147
|
+
{ content: 'System prompt.', role: 'system' },
|
|
148
|
+
{ content: 'Hello', role: 'user' },
|
|
149
|
+
];
|
|
133
150
|
|
|
134
151
|
const context = createContext(input);
|
|
135
152
|
const result = await injector.process(context);
|
|
136
153
|
|
|
137
|
-
|
|
154
|
+
// Check injected message content
|
|
155
|
+
expect(result.messages[1].content).toMatchSnapshot();
|
|
138
156
|
});
|
|
139
157
|
|
|
140
158
|
it('should handle empty config', async () => {
|
|
@@ -142,12 +160,16 @@ describe('GroupContextInjector', () => {
|
|
|
142
160
|
enabled: true,
|
|
143
161
|
});
|
|
144
162
|
|
|
145
|
-
const input: any[] = [
|
|
163
|
+
const input: any[] = [
|
|
164
|
+
{ content: 'Base prompt.', role: 'system' },
|
|
165
|
+
{ content: 'Hello', role: 'user' },
|
|
166
|
+
];
|
|
146
167
|
|
|
147
168
|
const context = createContext(input);
|
|
148
169
|
const result = await injector.process(context);
|
|
149
170
|
|
|
150
|
-
|
|
171
|
+
// Check injected message content
|
|
172
|
+
expect(result.messages[1].content).toMatchSnapshot();
|
|
151
173
|
});
|
|
152
174
|
});
|
|
153
175
|
|
|
@@ -158,15 +180,19 @@ describe('GroupContextInjector', () => {
|
|
|
158
180
|
// Minimal config
|
|
159
181
|
});
|
|
160
182
|
|
|
161
|
-
const input: any[] = [
|
|
183
|
+
const input: any[] = [
|
|
184
|
+
{ role: 'system', content: 'Base prompt.' },
|
|
185
|
+
{ role: 'user', content: 'Hello' },
|
|
186
|
+
];
|
|
162
187
|
|
|
163
188
|
const context = createContext(input);
|
|
164
189
|
const result = await injector.process(context);
|
|
165
190
|
|
|
166
|
-
|
|
191
|
+
// Check injected message content
|
|
192
|
+
const injectedContent = result.messages[1].content;
|
|
167
193
|
|
|
168
194
|
// Even with minimal config, identity rules should be present
|
|
169
|
-
expect(
|
|
195
|
+
expect(injectedContent).toMatchSnapshot();
|
|
170
196
|
});
|
|
171
197
|
});
|
|
172
198
|
|
|
@@ -179,12 +205,16 @@ describe('GroupContextInjector', () => {
|
|
|
179
205
|
systemPrompt: 'Empty group description',
|
|
180
206
|
});
|
|
181
207
|
|
|
182
|
-
const input: any[] = [
|
|
208
|
+
const input: any[] = [
|
|
209
|
+
{ content: 'Prompt.', role: 'system' },
|
|
210
|
+
{ content: 'Hello', role: 'user' },
|
|
211
|
+
];
|
|
183
212
|
|
|
184
213
|
const context = createContext(input);
|
|
185
214
|
const result = await injector.process(context);
|
|
186
215
|
|
|
187
|
-
|
|
216
|
+
// Check injected message content
|
|
217
|
+
expect(result.messages[1].content).toMatchSnapshot();
|
|
188
218
|
});
|
|
189
219
|
|
|
190
220
|
it('should preserve other messages unchanged', async () => {
|
|
@@ -204,10 +234,16 @@ describe('GroupContextInjector', () => {
|
|
|
204
234
|
const context = createContext(input);
|
|
205
235
|
const result = await injector.process(context);
|
|
206
236
|
|
|
207
|
-
//
|
|
208
|
-
expect(result.messages[0].content).
|
|
209
|
-
|
|
210
|
-
|
|
237
|
+
// System message should be unchanged
|
|
238
|
+
expect(result.messages[0].content).toBe('System prompt.');
|
|
239
|
+
|
|
240
|
+
// Injected message should be second
|
|
241
|
+
expect(result.messages[1].role).toBe('user');
|
|
242
|
+
expect(result.messages[1].content).toContain('<group_context>');
|
|
243
|
+
|
|
244
|
+
// Original messages should be preserved
|
|
245
|
+
expect(result.messages[2].content).toBe('User message.');
|
|
246
|
+
expect(result.messages[3].content).toBe('Assistant response.');
|
|
211
247
|
});
|
|
212
248
|
});
|
|
213
249
|
});
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
3
|
exports[`GroupContextInjector > Edge Cases > should handle empty members array 1`] = `
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
<group_context>
|
|
4
|
+
"<group_context>
|
|
7
5
|
You are "", acting as a in the multi-agent group "Empty Group".
|
|
8
6
|
Your internal agent ID is (for system use only, never expose to users).
|
|
9
7
|
|
|
@@ -24,9 +22,7 @@ Empty group description
|
|
|
24
22
|
`;
|
|
25
23
|
|
|
26
24
|
exports[`GroupContextInjector > Identity Rules Section > should always include identity rules 1`] = `
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
<group_context>
|
|
25
|
+
"<group_context>
|
|
30
26
|
You are "", acting as a in the multi-agent group "".
|
|
31
27
|
Your internal agent ID is (for system use only, never expose to users).
|
|
32
28
|
|
|
@@ -47,9 +43,7 @@ Your internal agent ID is (for system use only, never expose to users).
|
|
|
47
43
|
`;
|
|
48
44
|
|
|
49
45
|
exports[`GroupContextInjector > Variable Replacement > should handle config with only group info 1`] = `
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
<group_context>
|
|
46
|
+
"<group_context>
|
|
53
47
|
You are "", acting as a in the multi-agent group "Test Group".
|
|
54
48
|
Your internal agent ID is (for system use only, never expose to users).
|
|
55
49
|
|
|
@@ -70,9 +64,7 @@ Test group description
|
|
|
70
64
|
`;
|
|
71
65
|
|
|
72
66
|
exports[`GroupContextInjector > Variable Replacement > should handle config with only identity info 1`] = `
|
|
73
|
-
"
|
|
74
|
-
|
|
75
|
-
<group_context>
|
|
67
|
+
"<group_context>
|
|
76
68
|
You are "Editor", acting as a participant in the multi-agent group "".
|
|
77
69
|
Your internal agent ID is agt_editor (for system use only, never expose to users).
|
|
78
70
|
|
|
@@ -93,9 +85,7 @@ Your internal agent ID is agt_editor (for system use only, never expose to users
|
|
|
93
85
|
`;
|
|
94
86
|
|
|
95
87
|
exports[`GroupContextInjector > Variable Replacement > should handle empty config 1`] = `
|
|
96
|
-
"
|
|
97
|
-
|
|
98
|
-
<group_context>
|
|
88
|
+
"<group_context>
|
|
99
89
|
You are "", acting as a in the multi-agent group "".
|
|
100
90
|
Your internal agent ID is (for system use only, never expose to users).
|
|
101
91
|
|
package/packages/database/src/repositories/userMemory/__tests__/UserMemoryTopicRepository.test.ts
CHANGED
|
@@ -50,9 +50,30 @@ describe('UserMemoryTopicRepository', () => {
|
|
|
50
50
|
|
|
51
51
|
it('should return concatenated user message content', async () => {
|
|
52
52
|
await serverDB.insert(messages).values([
|
|
53
|
-
{
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
{
|
|
54
|
+
id: 'msg-1',
|
|
55
|
+
content: 'Hello',
|
|
56
|
+
role: 'user',
|
|
57
|
+
topicId,
|
|
58
|
+
userId,
|
|
59
|
+
createdAt: new Date('2024-01-01'),
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: 'msg-2',
|
|
63
|
+
content: 'Hi there!',
|
|
64
|
+
role: 'assistant',
|
|
65
|
+
topicId,
|
|
66
|
+
userId,
|
|
67
|
+
createdAt: new Date('2024-01-02'),
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: 'msg-3',
|
|
71
|
+
content: 'How are you?',
|
|
72
|
+
role: 'user',
|
|
73
|
+
topicId,
|
|
74
|
+
userId,
|
|
75
|
+
createdAt: new Date('2024-01-03'),
|
|
76
|
+
},
|
|
56
77
|
]);
|
|
57
78
|
|
|
58
79
|
const result = await repo.getUserMessagesQueryForTopic(topicId);
|
|
@@ -2,10 +2,8 @@ import debug from 'debug';
|
|
|
2
2
|
import { stat } from 'node:fs/promises';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { FileDocument, FileMetadata, SupportedFileType } from './types';
|
|
8
|
-
import type { DocumentPage, FileLoaderInterface } from './types';
|
|
5
|
+
import { getFileLoader } from './loaders';
|
|
6
|
+
import type { DocumentPage, FileDocument, FileMetadata, SupportedFileType } from './types';
|
|
9
7
|
import { isTextReadableFile } from './utils/isTextReadableFile';
|
|
10
8
|
|
|
11
9
|
const log = debug('file-loaders:loadFile');
|
|
@@ -64,9 +62,6 @@ const getFileType = (filePath: string): SupportedFileType | undefined => {
|
|
|
64
62
|
}
|
|
65
63
|
};
|
|
66
64
|
|
|
67
|
-
// Default fallback loader class
|
|
68
|
-
const DefaultLoader = TextLoader;
|
|
69
|
-
|
|
70
65
|
/**
|
|
71
66
|
* Loads a file from the specified path, automatically detecting the file type
|
|
72
67
|
* and using the appropriate loader class.
|
|
@@ -113,18 +108,18 @@ export const loadFile = async (
|
|
|
113
108
|
source,
|
|
114
109
|
});
|
|
115
110
|
|
|
116
|
-
const
|
|
117
|
-
log('Parser type determined as:',
|
|
111
|
+
const parserType = getFileType(filePath);
|
|
112
|
+
log('Parser type determined as:', parserType);
|
|
118
113
|
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
114
|
+
// Use lazy loading to get the loader class - this prevents heavy dependencies
|
|
115
|
+
// like pdfjs-dist from being loaded until they're actually needed
|
|
116
|
+
const loaderType = parserType ?? 'txt';
|
|
117
|
+
const LoaderClass = await getFileLoader(loaderType);
|
|
123
118
|
log('Selected loader class:', LoaderClass.name);
|
|
124
119
|
|
|
125
|
-
if (!
|
|
120
|
+
if (!parserType) {
|
|
126
121
|
console.warn(
|
|
127
|
-
`No specific loader found for file type '${fileType}'. Using default loader (
|
|
122
|
+
`No specific loader found for file type '${fileType}'. Using default loader (TextLoader) as fallback.`,
|
|
128
123
|
);
|
|
129
124
|
}
|
|
130
125
|
|
|
@@ -1,21 +1,70 @@
|
|
|
1
|
-
import { FileLoaderInterface, SupportedFileType } from '../types';
|
|
2
|
-
import { DocLoader } from './doc';
|
|
3
|
-
import { DocxLoader } from './docx';
|
|
4
|
-
// import { EpubLoader } from './epub';
|
|
5
|
-
import { ExcelLoader } from './excel';
|
|
6
|
-
import { PdfLoader } from './pdf';
|
|
7
|
-
import { PptxLoader } from './pptx';
|
|
8
|
-
import { TextLoader } from './text';
|
|
1
|
+
import type { FileLoaderInterface, SupportedFileType } from '../types';
|
|
9
2
|
|
|
10
|
-
//
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
3
|
+
// Lazy loader factory type - returns a Promise that resolves to the loader class
|
|
4
|
+
type LazyLoaderFactory = () => Promise<new () => FileLoaderInterface>;
|
|
5
|
+
|
|
6
|
+
// Loader configuration map using lazy imports
|
|
7
|
+
// This prevents pdfjs-dist from being loaded at module initialization
|
|
8
|
+
// and only loads it when PDF files need to be processed
|
|
9
|
+
const lazyFileLoaders: Record<SupportedFileType, LazyLoaderFactory> = {
|
|
10
|
+
doc: async () => {
|
|
11
|
+
const { DocLoader } = await import('./doc');
|
|
12
|
+
return DocLoader;
|
|
13
|
+
},
|
|
14
|
+
docx: async () => {
|
|
15
|
+
const { DocxLoader } = await import('./docx');
|
|
16
|
+
return DocxLoader;
|
|
17
|
+
},
|
|
18
|
+
excel: async () => {
|
|
19
|
+
const { ExcelLoader } = await import('./excel');
|
|
20
|
+
return ExcelLoader;
|
|
21
|
+
},
|
|
22
|
+
pdf: async () => {
|
|
23
|
+
// Polyfill DOMMatrix for Node.js environment before importing pdfjs-dist
|
|
24
|
+
// pdfjs-dist 5.x uses DOMMatrix at module initialization which doesn't exist in Node.js
|
|
25
|
+
if (typeof globalThis.DOMMatrix === 'undefined') {
|
|
26
|
+
try {
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
28
|
+
const canvas = require('@napi-rs/canvas');
|
|
29
|
+
globalThis.DOMMatrix = canvas.DOMMatrix;
|
|
30
|
+
globalThis.DOMPoint = canvas.DOMPoint;
|
|
31
|
+
globalThis.DOMRect = canvas.DOMRect;
|
|
32
|
+
globalThis.Path2D = canvas.Path2D;
|
|
33
|
+
} catch {
|
|
34
|
+
// @napi-rs/canvas not available, pdfjs-dist may fail if DOMMatrix is needed
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const { PdfLoader } = await import('./pdf');
|
|
38
|
+
return PdfLoader;
|
|
39
|
+
},
|
|
40
|
+
pptx: async () => {
|
|
41
|
+
const { PptxLoader } = await import('./pptx');
|
|
42
|
+
return PptxLoader;
|
|
43
|
+
},
|
|
44
|
+
txt: async () => {
|
|
45
|
+
const { TextLoader } = await import('./text');
|
|
46
|
+
return TextLoader;
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get a file loader class for the specified file type.
|
|
52
|
+
* Uses dynamic imports to avoid loading heavy dependencies (like pdfjs-dist) until needed.
|
|
53
|
+
* Falls back to TextLoader if no specific loader is found.
|
|
54
|
+
*/
|
|
55
|
+
export const getFileLoader = async (
|
|
56
|
+
fileType: SupportedFileType | string,
|
|
57
|
+
): Promise<new () => FileLoaderInterface> => {
|
|
58
|
+
const loaderFactory = lazyFileLoaders[fileType as SupportedFileType];
|
|
59
|
+
if (!loaderFactory) {
|
|
60
|
+
// Fallback to TextLoader for unsupported file types
|
|
61
|
+
const { TextLoader } = await import('./text');
|
|
62
|
+
return TextLoader;
|
|
63
|
+
}
|
|
64
|
+
return loaderFactory();
|
|
21
65
|
};
|
|
66
|
+
|
|
67
|
+
// For backward compatibility - but prefer using getFileLoader for lazy loading
|
|
68
|
+
// This is kept to avoid breaking existing imports, but it will trigger immediate loading
|
|
69
|
+
// of all loaders. Consider migrating to getFileLoader.
|
|
70
|
+
export { lazyFileLoaders as fileLoaderFactories };
|
|
@@ -12,7 +12,6 @@ const ComfyUI: ModelProviderCard = {
|
|
|
12
12
|
chatModels: [],
|
|
13
13
|
description:
|
|
14
14
|
'A powerful open-source workflow engine for image, video, and audio generation, supporting models like SD, FLUX, Qwen, Hunyuan, and WAN with node-based editing and private deployment.',
|
|
15
|
-
enabled: true,
|
|
16
15
|
id: 'comfyui',
|
|
17
16
|
name: 'ComfyUI',
|
|
18
17
|
settings: {
|
|
@@ -5,8 +5,7 @@ export const ChatErrorType = {
|
|
|
5
5
|
// ******* Business Error Semantics ******* //
|
|
6
6
|
|
|
7
7
|
InvalidAccessCode: 'InvalidAccessCode', // is in valid password
|
|
8
|
-
|
|
9
|
-
FreePlanLimit: 'FreePlanLimit', // is not Clerk User
|
|
8
|
+
FreePlanLimit: 'FreePlanLimit', // Free plan usage limit
|
|
10
9
|
SubscriptionPlanLimit: 'SubscriptionPlanLimit', // Subscription user limit exceeded
|
|
11
10
|
SubscriptionKeyMismatch: 'SubscriptionKeyMismatch', // Subscription key mismatch
|
|
12
11
|
|
|
@@ -4,34 +4,17 @@ import { extractBearerToken, getUserAuth } from '../auth';
|
|
|
4
4
|
|
|
5
5
|
// Mock auth constants
|
|
6
6
|
let mockEnableBetterAuth = false;
|
|
7
|
-
let mockEnableClerk = false;
|
|
8
7
|
let mockEnableNextAuth = false;
|
|
9
8
|
|
|
10
9
|
vi.mock('@/envs/auth', () => ({
|
|
11
10
|
get enableBetterAuth() {
|
|
12
11
|
return mockEnableBetterAuth;
|
|
13
12
|
},
|
|
14
|
-
get enableClerk() {
|
|
15
|
-
return mockEnableClerk;
|
|
16
|
-
},
|
|
17
13
|
get enableNextAuth() {
|
|
18
14
|
return mockEnableNextAuth;
|
|
19
15
|
},
|
|
20
16
|
}));
|
|
21
17
|
|
|
22
|
-
vi.mock('@/libs/clerk-auth', () => ({
|
|
23
|
-
ClerkAuth: class {
|
|
24
|
-
async getAuth() {
|
|
25
|
-
return {
|
|
26
|
-
clerkAuth: {
|
|
27
|
-
redirectToSignIn: vi.fn(),
|
|
28
|
-
},
|
|
29
|
-
userId: 'clerk-user-id',
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
}));
|
|
34
|
-
|
|
35
18
|
vi.mock('@/libs/next-auth', () => ({
|
|
36
19
|
default: {
|
|
37
20
|
auth: vi.fn().mockResolvedValue({
|
|
@@ -62,7 +45,6 @@ describe('getUserAuth', () => {
|
|
|
62
45
|
beforeEach(() => {
|
|
63
46
|
vi.clearAllMocks();
|
|
64
47
|
mockEnableBetterAuth = false;
|
|
65
|
-
mockEnableClerk = false;
|
|
66
48
|
mockEnableNextAuth = false;
|
|
67
49
|
});
|
|
68
50
|
|
|
@@ -70,22 +52,7 @@ describe('getUserAuth', () => {
|
|
|
70
52
|
await expect(getUserAuth()).rejects.toThrow('Auth method is not enabled');
|
|
71
53
|
});
|
|
72
54
|
|
|
73
|
-
it('should return clerk auth when clerk is enabled', async () => {
|
|
74
|
-
mockEnableClerk = true;
|
|
75
|
-
mockEnableNextAuth = false;
|
|
76
|
-
|
|
77
|
-
const auth = await getUserAuth();
|
|
78
|
-
|
|
79
|
-
expect(auth).toEqual({
|
|
80
|
-
clerkAuth: {
|
|
81
|
-
redirectToSignIn: expect.any(Function),
|
|
82
|
-
},
|
|
83
|
-
userId: 'clerk-user-id',
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
55
|
it('should return next auth when next auth is enabled', async () => {
|
|
88
|
-
mockEnableClerk = false;
|
|
89
56
|
mockEnableNextAuth = true;
|
|
90
57
|
|
|
91
58
|
const auth = await getUserAuth();
|
|
@@ -100,20 +67,6 @@ describe('getUserAuth', () => {
|
|
|
100
67
|
});
|
|
101
68
|
});
|
|
102
69
|
|
|
103
|
-
it('should prioritize clerk auth over next auth when both are enabled', async () => {
|
|
104
|
-
mockEnableClerk = true;
|
|
105
|
-
mockEnableNextAuth = true;
|
|
106
|
-
|
|
107
|
-
const auth = await getUserAuth();
|
|
108
|
-
|
|
109
|
-
expect(auth).toEqual({
|
|
110
|
-
clerkAuth: {
|
|
111
|
-
redirectToSignIn: expect.any(Function),
|
|
112
|
-
},
|
|
113
|
-
userId: 'clerk-user-id',
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
|
|
117
70
|
it('should return better auth when better auth is enabled', async () => {
|
|
118
71
|
mockEnableBetterAuth = true;
|
|
119
72
|
|
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
import { headers } from 'next/headers';
|
|
2
2
|
|
|
3
|
-
import { enableBetterAuth,
|
|
3
|
+
import { enableBetterAuth, enableNextAuth } from '@/envs/auth';
|
|
4
4
|
|
|
5
5
|
export const getUserAuth = async () => {
|
|
6
|
-
if (enableClerk) {
|
|
7
|
-
const { ClerkAuth } = await import('@/libs/clerk-auth');
|
|
8
|
-
|
|
9
|
-
const clerkAuth = new ClerkAuth();
|
|
10
|
-
|
|
11
|
-
return await clerkAuth.getAuth();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
6
|
if (enableBetterAuth) {
|
|
15
7
|
const { auth: betterAuth } = await import('@/auth');
|
|
16
8
|
|
package/pnpm-workspace.yaml
CHANGED