@lobehub/lobehub 2.0.0-next.267 → 2.0.0-next.268

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 (126) hide show
  1. package/.cursor/rules/microcopy-cn.mdc +75 -63
  2. package/.cursor/rules/microcopy-en.mdc +4 -8
  3. package/CHANGELOG.md +25 -0
  4. package/README.md +8 -8
  5. package/README.zh-CN.md +8 -8
  6. package/apps/desktop/src/main/locales/default/common.ts +2 -2
  7. package/changelog/v1.json +5 -0
  8. package/docs/development/database-schema.dbml +4 -0
  9. package/e2e/CLAUDE.md +9 -8
  10. package/e2e/cucumber.config.js +1 -0
  11. package/e2e/src/features/page/README.md +118 -0
  12. package/e2e/src/features/page/crud.feature +62 -0
  13. package/e2e/src/features/page/editor-content.feature +93 -0
  14. package/e2e/src/features/page/editor-meta.feature +60 -0
  15. package/e2e/src/steps/agent/conversation.steps.ts +4 -4
  16. package/e2e/src/steps/home/sidebarAgent.steps.ts +91 -94
  17. package/e2e/src/steps/home/sidebarGroup.steps.ts +4 -4
  18. package/e2e/src/steps/hooks.ts +2 -0
  19. package/e2e/src/steps/page/editor-content.steps.ts +344 -0
  20. package/e2e/src/steps/page/editor-meta.steps.ts +410 -0
  21. package/e2e/src/steps/page/page-crud.steps.ts +363 -0
  22. package/e2e/src/support/world.ts +12 -0
  23. package/locales/ar/file.json +2 -0
  24. package/locales/bg-BG/file.json +2 -0
  25. package/locales/de-DE/file.json +2 -0
  26. package/locales/en-US/auth.json +1 -1
  27. package/locales/en-US/file.json +2 -0
  28. package/locales/en-US/metadata.json +2 -2
  29. package/locales/es-ES/file.json +2 -0
  30. package/locales/fa-IR/file.json +2 -0
  31. package/locales/fr-FR/file.json +2 -0
  32. package/locales/it-IT/file.json +2 -0
  33. package/locales/ja-JP/file.json +2 -0
  34. package/locales/ko-KR/file.json +2 -0
  35. package/locales/nl-NL/file.json +2 -0
  36. package/locales/pl-PL/file.json +2 -0
  37. package/locales/pt-BR/file.json +2 -0
  38. package/locales/ru-RU/file.json +2 -0
  39. package/locales/tr-TR/file.json +2 -0
  40. package/locales/vi-VN/file.json +2 -0
  41. package/locales/zh-CN/file.json +2 -0
  42. package/locales/zh-TW/file.json +2 -0
  43. package/package.json +1 -1
  44. package/packages/builtin-agents/src/agents/agent-builder/index.ts +1 -1
  45. package/packages/builtin-agents/src/agents/group-agent-builder/index.ts +1 -1
  46. package/packages/builtin-agents/src/agents/page-agent/index.ts +1 -1
  47. package/packages/const/src/settings/group.ts +0 -10
  48. package/packages/database/migrations/0068_update_group_data.sql +4 -0
  49. package/packages/database/migrations/meta/0068_snapshot.json +9588 -0
  50. package/packages/database/migrations/meta/_journal.json +7 -0
  51. package/packages/database/src/models/__tests__/chatGroup.test.ts +5 -7
  52. package/packages/database/src/models/__tests__/knowledgeBase.test.ts +185 -0
  53. package/packages/database/src/models/knowledgeBase.ts +67 -3
  54. package/packages/database/src/repositories/agentGroup/index.test.ts +23 -29
  55. package/packages/database/src/repositories/agentGroup/index.ts +4 -9
  56. package/packages/database/src/repositories/knowledge/index.ts +3 -3
  57. package/packages/database/src/schemas/chatGroup.ts +4 -3
  58. package/packages/database/src/types/chatGroup.ts +0 -7
  59. package/packages/types/src/agentGroup/index.ts +30 -9
  60. package/src/app/[variants]/(main)/home/_layout/Body/Agent/ModalProvider.tsx +9 -32
  61. package/src/app/[variants]/(main)/home/_layout/hooks/useCreateMenuItems.tsx +3 -37
  62. package/src/app/[variants]/(main)/home/_layout/hooks/useSessionGroupMenuItems.tsx +7 -53
  63. package/src/app/[variants]/(main)/home/features/RecentPage/List.tsx +2 -1
  64. package/src/app/[variants]/(main)/resource/features/DndContextWrapper.tsx +1 -1
  65. package/src/app/[variants]/(main)/resource/library/_layout/Sidebar.tsx +2 -2
  66. package/src/app/[variants]/(main)/resource/library/features/LibraryMenu.tsx +2 -2
  67. package/src/app/[variants]/(mobile)/chat/settings/features/SettingButton.tsx +2 -12
  68. package/src/components/ChatGroupWizard/ChatGroupWizard.tsx +5 -27
  69. package/src/components/DragUpload/index.tsx +24 -27
  70. package/src/components/MemberSelectionModal/MemberSelectionModal.tsx +2 -11
  71. package/src/features/CommandMenu/useCommandMenu.ts +4 -14
  72. package/src/features/ResourceManager/components/Editor/index.tsx +2 -3
  73. package/src/features/ResourceManager/components/Explorer/Header/index.tsx +13 -17
  74. package/src/features/ResourceManager/components/Explorer/ItemDropdown/useFileItemDropdown.tsx +1 -1
  75. package/src/features/ResourceManager/components/Explorer/ListView/ListItem/TruncatedFileName.tsx +130 -0
  76. package/src/features/ResourceManager/components/Explorer/ListView/ListItem/index.tsx +36 -4
  77. package/src/features/ResourceManager/components/Explorer/ListView/Skeleton.tsx +4 -3
  78. package/src/features/ResourceManager/components/Explorer/ListView/index.tsx +58 -2
  79. package/src/features/ResourceManager/components/Explorer/MasonryView/index.tsx +58 -6
  80. package/src/features/ResourceManager/components/Explorer/MoveToFolderModal.tsx +2 -5
  81. package/src/features/ResourceManager/components/Explorer/ToolBar/BatchActionsDropdown.tsx +9 -5
  82. package/src/features/ResourceManager/components/Explorer/index.tsx +11 -56
  83. package/src/features/ResourceManager/components/Header/AddButton.tsx +5 -6
  84. package/src/features/ResourceManager/components/LibraryHierarchy/HierarchyNode.tsx +382 -0
  85. package/src/features/ResourceManager/components/LibraryHierarchy/index.tsx +396 -0
  86. package/src/features/ResourceManager/components/LibraryHierarchy/styles.ts +19 -0
  87. package/src/features/ResourceManager/components/LibraryHierarchy/treeState.ts +178 -0
  88. package/src/features/ResourceManager/components/LibraryHierarchy/types.ts +10 -0
  89. package/src/features/ResourceManager/index.tsx +3 -0
  90. package/src/layout/GlobalProvider/GroupWizardProvider.tsx +6 -29
  91. package/src/locales/default/auth.ts +1 -1
  92. package/src/locales/default/file.ts +2 -0
  93. package/src/locales/default/metadata.ts +2 -2
  94. package/src/server/modules/AgentRuntime/AgentRuntimeCoordinator.ts +30 -30
  95. package/src/server/modules/AgentRuntime/AgentStateManager.ts +23 -23
  96. package/src/server/modules/AgentRuntime/InMemoryAgentStateManager.ts +16 -16
  97. package/src/server/modules/AgentRuntime/InMemoryStreamEventManager.ts +13 -13
  98. package/src/server/modules/AgentRuntime/RuntimeExecutors.ts +2 -2
  99. package/src/server/modules/AgentRuntime/StreamEventManager.ts +18 -18
  100. package/src/server/modules/AgentRuntime/types.ts +21 -21
  101. package/src/server/routers/lambda/__tests__/agentGroup.test.ts +8 -8
  102. package/src/server/routers/lambda/agentGroup.ts +10 -12
  103. package/src/server/services/document/index.ts +1 -0
  104. package/src/store/agentGroup/slices/curd.test.ts +4 -4
  105. package/src/store/file/slices/fileManager/action.ts +12 -4
  106. package/src/store/home/slices/homeInput/action.ts +0 -3
  107. package/src/store/session/slices/session/action.ts +5 -9
  108. package/src/app/[variants]/(mobile)/chat/settings/features/AgentTeamSettings/index.tsx +0 -95
  109. package/src/features/GroupChatSettings/AgentCard.tsx +0 -154
  110. package/src/features/GroupChatSettings/AgentTeamChatSettings.tsx +0 -179
  111. package/src/features/GroupChatSettings/AgentTeamMembersSettings.tsx +0 -244
  112. package/src/features/GroupChatSettings/AgentTeamMetaSettings.tsx +0 -94
  113. package/src/features/GroupChatSettings/AgentTeamSettings.tsx +0 -54
  114. package/src/features/GroupChatSettings/GroupCategory/index.tsx +0 -30
  115. package/src/features/GroupChatSettings/GroupCategory/useGroupCategory.tsx +0 -42
  116. package/src/features/GroupChatSettings/GroupChatSettingsProvider.tsx +0 -19
  117. package/src/features/GroupChatSettings/HostMemberCard.tsx +0 -113
  118. package/src/features/GroupChatSettings/StoreUpdater.tsx +0 -34
  119. package/src/features/GroupChatSettings/hooks/useGroupChatSettings.ts +0 -25
  120. package/src/features/GroupChatSettings/index.ts +0 -16
  121. package/src/features/GroupChatSettings/store/action.ts +0 -105
  122. package/src/features/GroupChatSettings/store/index.ts +0 -18
  123. package/src/features/GroupChatSettings/store/initialState.ts +0 -23
  124. package/src/features/GroupChatSettings/store/selectors.ts +0 -13
  125. package/src/features/ResourceManager/components/Tree/index.tsx +0 -883
  126. /package/src/features/ResourceManager/components/{Tree → LibraryHierarchy}/TreeSkeleton.tsx +0 -0
@@ -0,0 +1,344 @@
1
+ /**
2
+ * Page Editor Content Steps
3
+ *
4
+ * Step definitions for Page editor rich text editing E2E tests
5
+ */
6
+ import { Then, When } from '@cucumber/cucumber';
7
+ import { expect } from '@playwright/test';
8
+
9
+ import { CustomWorld } from '../../support/world';
10
+
11
+ // ============================================
12
+ // Helper Functions
13
+ // ============================================
14
+
15
+ /**
16
+ * Get the contenteditable editor element
17
+ */
18
+ async function getEditor(world: CustomWorld) {
19
+ const editor = world.page.locator('[contenteditable="true"]').first();
20
+ await expect(editor).toBeVisible({ timeout: 5000 });
21
+ return editor;
22
+ }
23
+
24
+ // ============================================
25
+ // When Steps - Basic Text
26
+ // ============================================
27
+
28
+ When('用户点击编辑器内容区域', async function (this: CustomWorld) {
29
+ console.log(' 📍 Step: 点击编辑器内容区域...');
30
+
31
+ const editorContent = this.page.locator('[contenteditable="true"]').first();
32
+ if ((await editorContent.count()) > 0) {
33
+ await editorContent.click();
34
+ } else {
35
+ // Fallback: click somewhere else
36
+ await this.page.click('body', { position: { x: 400, y: 400 } });
37
+ }
38
+ await this.page.waitForTimeout(500);
39
+
40
+ console.log(' ✅ 已点击编辑器内容区域');
41
+ });
42
+
43
+ When('用户按下 Enter 键', async function (this: CustomWorld) {
44
+ console.log(' 📍 Step: 按下 Enter 键...');
45
+
46
+ await this.page.keyboard.press('Enter');
47
+ // Wait for debounce save (1000ms) + buffer
48
+ await this.page.waitForTimeout(1500);
49
+
50
+ console.log(' ✅ 已按下 Enter 键');
51
+ });
52
+
53
+ When('用户输入文本 {string}', async function (this: CustomWorld, text: string) {
54
+ console.log(` 📍 Step: 输入文本 "${text}"...`);
55
+
56
+ await this.page.keyboard.type(text, { delay: 30 });
57
+ await this.page.waitForTimeout(300);
58
+
59
+ // Store for later verification
60
+ this.testContext.inputText = text;
61
+
62
+ console.log(` ✅ 已输入文本 "${text}"`);
63
+ });
64
+
65
+ When('用户在编辑器中输入内容 {string}', async function (this: CustomWorld, content: string) {
66
+ console.log(` 📍 Step: 在编辑器中输入内容 "${content}"...`);
67
+
68
+ const editor = await getEditor(this);
69
+ await editor.click();
70
+ await this.page.waitForTimeout(300);
71
+ await this.page.keyboard.type(content, { delay: 30 });
72
+ await this.page.waitForTimeout(300);
73
+
74
+ this.testContext.inputText = content;
75
+
76
+ console.log(` ✅ 已输入内容 "${content}"`);
77
+ });
78
+
79
+ When('用户选中所有内容', async function (this: CustomWorld) {
80
+ console.log(' 📍 Step: 选中所有内容...');
81
+
82
+ await this.page.keyboard.press(`${this.modKey}+A`);
83
+ await this.page.waitForTimeout(300);
84
+
85
+ console.log(' ✅ 已选中所有内容');
86
+ });
87
+
88
+ // ============================================
89
+ // When Steps - Slash Commands
90
+ // ============================================
91
+
92
+ When('用户输入斜杠 {string}', async function (this: CustomWorld, slash: string) {
93
+ console.log(` 📍 Step: 输入斜杠 "${slash}"...`);
94
+
95
+ await this.page.keyboard.type(slash, { delay: 50 });
96
+ // Wait for slash menu to appear
97
+ await this.page.waitForTimeout(500);
98
+
99
+ console.log(` ✅ 已输入斜杠 "${slash}"`);
100
+ });
101
+
102
+ When('用户输入斜杠命令 {string}', async function (this: CustomWorld, command: string) {
103
+ console.log(` 📍 Step: 输入斜杠命令 "${command}"...`);
104
+
105
+ // The command format is "/shortcut" (e.g., "/h1", "/codeblock")
106
+ // First type the slash and wait for menu
107
+ await this.page.keyboard.type('/', { delay: 100 });
108
+ await this.page.waitForTimeout(800); // Wait for slash menu to appear
109
+
110
+ // Then type the rest of the command (without the leading /)
111
+ const shortcut = command.startsWith('/') ? command.slice(1) : command;
112
+ await this.page.keyboard.type(shortcut, { delay: 80 });
113
+ await this.page.waitForTimeout(500); // Wait for menu to filter
114
+
115
+ console.log(` ✅ 已输入斜杠命令 "${command}"`);
116
+ });
117
+
118
+ // ============================================
119
+ // When Steps - Formatting
120
+ // ============================================
121
+
122
+ When('用户按下快捷键 {string}', async function (this: CustomWorld, shortcut: string) {
123
+ console.log(` 📍 Step: 按下快捷键 "${shortcut}"...`);
124
+
125
+ // Convert Meta to platform-specific modifier key for cross-platform support
126
+ const platformShortcut = shortcut.replaceAll('Meta', this.modKey);
127
+ await this.page.keyboard.press(platformShortcut);
128
+ await this.page.waitForTimeout(300);
129
+
130
+ console.log(` ✅ 已按下快捷键 "${platformShortcut}"`);
131
+ });
132
+
133
+ // ============================================
134
+ // Then Steps - Basic Text
135
+ // ============================================
136
+
137
+ Then('编辑器应该显示输入的文本', async function (this: CustomWorld) {
138
+ console.log(' 📍 Step: 验证编辑器显示输入的文本...');
139
+
140
+ const editor = await getEditor(this);
141
+ const text = this.testContext.inputText;
142
+
143
+ // Check if the text is visible in the editor
144
+ const editorText = await editor.textContent();
145
+ expect(editorText).toContain(text);
146
+
147
+ console.log(` ✅ 编辑器显示文本: "${text}"`);
148
+ });
149
+
150
+ Then('编辑器应该显示 {string}', async function (this: CustomWorld, expectedText: string) {
151
+ console.log(` 📍 Step: 验证编辑器显示 "${expectedText}"...`);
152
+
153
+ const editor = await getEditor(this);
154
+ const editorText = await editor.textContent();
155
+ expect(editorText).toContain(expectedText);
156
+
157
+ console.log(` ✅ 编辑器显示 "${expectedText}"`);
158
+ });
159
+
160
+ // ============================================
161
+ // Then Steps - Slash Commands
162
+ // ============================================
163
+
164
+ Then('应该显示斜杠命令菜单', async function (this: CustomWorld) {
165
+ console.log(' 📍 Step: 验证显示斜杠命令菜单...');
166
+
167
+ // The slash menu should be visible
168
+ // Look for menu with heading options, list options, etc.
169
+ const menuSelectors = ['[role="menu"]', '[role="listbox"]', '.slash-menu', '[data-slash-menu]'];
170
+
171
+ let menuFound = false;
172
+ for (const selector of menuSelectors) {
173
+ const menu = this.page.locator(selector);
174
+ if ((await menu.count()) > 0 && (await menu.isVisible())) {
175
+ menuFound = true;
176
+ break;
177
+ }
178
+ }
179
+
180
+ // Alternative: look for menu items by text
181
+ if (!menuFound) {
182
+ const headingOption = this.page.getByText(/heading|标题/i).first();
183
+ const listOption = this.page.getByText(/list|列表/i).first();
184
+
185
+ menuFound =
186
+ ((await headingOption.count()) > 0 && (await headingOption.isVisible())) ||
187
+ ((await listOption.count()) > 0 && (await listOption.isVisible()));
188
+ }
189
+
190
+ expect(menuFound).toBe(true);
191
+
192
+ console.log(' ✅ 斜杠命令菜单已显示');
193
+ });
194
+
195
+ Then('编辑器应该包含一级标题', async function (this: CustomWorld) {
196
+ console.log(' 📍 Step: 验证编辑器包含一级标题...');
197
+
198
+ // Check for h1 element in the editor
199
+ const editor = await getEditor(this);
200
+ const h1 = editor.locator('h1');
201
+
202
+ await expect(h1).toBeVisible({ timeout: 5000 });
203
+
204
+ console.log(' ✅ 编辑器包含一级标题');
205
+ });
206
+
207
+ Then('编辑器应该包含无序列表', async function (this: CustomWorld) {
208
+ console.log(' 📍 Step: 验证编辑器包含无序列表...');
209
+
210
+ const editor = await getEditor(this);
211
+ const ul = editor.locator('ul');
212
+
213
+ await expect(ul).toBeVisible({ timeout: 5000 });
214
+
215
+ console.log(' ✅ 编辑器包含无序列表');
216
+ });
217
+
218
+ Then('编辑器应该包含任务列表', async function (this: CustomWorld) {
219
+ console.log(' 📍 Step: 验证编辑器包含任务列表...');
220
+
221
+ const editor = await getEditor(this);
222
+
223
+ // Task list usually has checkbox elements
224
+ const checkboxSelectors = [
225
+ 'input[type="checkbox"]',
226
+ '[role="checkbox"]',
227
+ '[data-lexical-check-list]',
228
+ 'li[role="listitem"] input',
229
+ ];
230
+
231
+ let found = false;
232
+ for (const selector of checkboxSelectors) {
233
+ const checkbox = editor.locator(selector);
234
+ if ((await checkbox.count()) > 0) {
235
+ found = true;
236
+ break;
237
+ }
238
+ }
239
+
240
+ // Alternative: check for specific class or structure
241
+ if (!found) {
242
+ const listItem = editor.locator('li');
243
+ found = (await listItem.count()) > 0;
244
+ }
245
+
246
+ expect(found).toBe(true);
247
+
248
+ console.log(' ✅ 编辑器包含任务列表');
249
+ });
250
+
251
+ Then('编辑器应该包含代码块', async function (this: CustomWorld) {
252
+ console.log(' 📍 Step: 验证编辑器包含代码块...');
253
+
254
+ // Code block might be rendered inside the editor OR as a sibling element
255
+ // CodeMirror renders its own container
256
+
257
+ // First check inside the editor
258
+ const editor = await getEditor(this);
259
+ const codeBlockSelectors = [
260
+ 'pre',
261
+ 'code',
262
+ '.cm-editor', // CodeMirror
263
+ '[data-language]',
264
+ '.code-block',
265
+ ];
266
+
267
+ let found = false;
268
+ for (const selector of codeBlockSelectors) {
269
+ const codeBlock = editor.locator(selector);
270
+ if ((await codeBlock.count()) > 0) {
271
+ found = true;
272
+ break;
273
+ }
274
+ }
275
+
276
+ // If not found inside editor, check the whole page
277
+ // CodeMirror might render outside the contenteditable
278
+ if (!found) {
279
+ for (const selector of codeBlockSelectors) {
280
+ const codeBlock = this.page.locator(selector);
281
+ if ((await codeBlock.count()) > 0 && (await codeBlock.isVisible())) {
282
+ found = true;
283
+ break;
284
+ }
285
+ }
286
+ }
287
+
288
+ expect(found).toBe(true);
289
+
290
+ console.log(' ✅ 编辑器包含代码块');
291
+ });
292
+
293
+ // ============================================
294
+ // Then Steps - Formatting
295
+ // ============================================
296
+
297
+ Then('选中的文本应该被加粗', async function (this: CustomWorld) {
298
+ console.log(' 📍 Step: 验证文本已加粗...');
299
+
300
+ const editor = await getEditor(this);
301
+
302
+ // Check for bold element (strong or b tag, or font-weight style)
303
+ const boldSelectors = [
304
+ 'strong',
305
+ 'b',
306
+ '[style*="font-weight: bold"]',
307
+ '[style*="font-weight: 700"]',
308
+ ];
309
+
310
+ let found = false;
311
+ for (const selector of boldSelectors) {
312
+ const boldElement = editor.locator(selector);
313
+ if ((await boldElement.count()) > 0) {
314
+ found = true;
315
+ break;
316
+ }
317
+ }
318
+
319
+ expect(found).toBe(true);
320
+
321
+ console.log(' ✅ 文本已加粗');
322
+ });
323
+
324
+ Then('选中的文本应该变为斜体', async function (this: CustomWorld) {
325
+ console.log(' 📍 Step: 验证文本已斜体...');
326
+
327
+ const editor = await getEditor(this);
328
+
329
+ // Check for italic element (em or i tag, or font-style style)
330
+ const italicSelectors = ['em', 'i', '[style*="font-style: italic"]'];
331
+
332
+ let found = false;
333
+ for (const selector of italicSelectors) {
334
+ const italicElement = editor.locator(selector);
335
+ if ((await italicElement.count()) > 0) {
336
+ found = true;
337
+ break;
338
+ }
339
+ }
340
+
341
+ expect(found).toBe(true);
342
+
343
+ console.log(' ✅ 文本已斜体');
344
+ });