@lobehub/lobehub 2.0.0-next.187 → 2.0.0-next.189

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 (177) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v1.json +18 -0
  3. package/e2e/CLAUDE.md +109 -2
  4. package/e2e/docs/llm-mock.md +68 -0
  5. package/e2e/docs/local-setup.md +354 -0
  6. package/e2e/docs/testing-tips.md +94 -0
  7. package/e2e/src/features/journeys/agent/agent-conversation.feature +0 -32
  8. package/e2e/src/mocks/llm/index.ts +6 -6
  9. package/e2e/src/steps/agent/conversation.steps.ts +3 -471
  10. package/locales/ar/models.json +89 -5
  11. package/locales/ar/plugin.json +5 -0
  12. package/locales/ar/providers.json +1 -0
  13. package/locales/bg-BG/models.json +68 -0
  14. package/locales/bg-BG/plugin.json +5 -0
  15. package/locales/bg-BG/providers.json +1 -0
  16. package/locales/de-DE/models.json +85 -0
  17. package/locales/de-DE/plugin.json +5 -0
  18. package/locales/de-DE/providers.json +1 -0
  19. package/locales/en-US/models.json +11 -10
  20. package/locales/en-US/plugin.json +5 -0
  21. package/locales/en-US/providers.json +1 -0
  22. package/locales/es-ES/models.json +72 -0
  23. package/locales/es-ES/plugin.json +5 -0
  24. package/locales/es-ES/providers.json +1 -0
  25. package/locales/fa-IR/models.json +86 -0
  26. package/locales/fa-IR/plugin.json +5 -0
  27. package/locales/fa-IR/providers.json +1 -0
  28. package/locales/fr-FR/models.json +49 -0
  29. package/locales/fr-FR/plugin.json +5 -0
  30. package/locales/fr-FR/providers.json +1 -0
  31. package/locales/it-IT/models.json +82 -0
  32. package/locales/it-IT/plugin.json +5 -0
  33. package/locales/it-IT/providers.json +1 -0
  34. package/locales/ja-JP/models.json +42 -5
  35. package/locales/ja-JP/plugin.json +5 -0
  36. package/locales/ja-JP/providers.json +1 -0
  37. package/locales/ko-KR/models.json +54 -0
  38. package/locales/ko-KR/plugin.json +5 -0
  39. package/locales/ko-KR/providers.json +1 -0
  40. package/locales/nl-NL/models.json +12 -1
  41. package/locales/nl-NL/plugin.json +5 -0
  42. package/locales/nl-NL/providers.json +1 -0
  43. package/locales/pl-PL/models.json +46 -0
  44. package/locales/pl-PL/plugin.json +5 -0
  45. package/locales/pl-PL/providers.json +1 -0
  46. package/locales/pt-BR/models.json +59 -0
  47. package/locales/pt-BR/plugin.json +5 -0
  48. package/locales/pt-BR/providers.json +1 -0
  49. package/locales/ru-RU/models.json +85 -0
  50. package/locales/ru-RU/plugin.json +5 -0
  51. package/locales/ru-RU/providers.json +1 -0
  52. package/locales/tr-TR/models.json +81 -0
  53. package/locales/tr-TR/plugin.json +5 -0
  54. package/locales/tr-TR/providers.json +1 -0
  55. package/locales/vi-VN/models.json +54 -0
  56. package/locales/vi-VN/plugin.json +5 -0
  57. package/locales/vi-VN/providers.json +1 -0
  58. package/locales/zh-CN/models.json +42 -5
  59. package/locales/zh-CN/plugin.json +5 -0
  60. package/locales/zh-CN/providers.json +1 -0
  61. package/locales/zh-TW/models.json +85 -0
  62. package/locales/zh-TW/plugin.json +5 -0
  63. package/locales/zh-TW/providers.json +1 -0
  64. package/package.json +2 -2
  65. package/packages/builtin-tool-gtd/src/manifest.ts +13 -8
  66. package/packages/builtin-tool-gtd/src/systemRole.ts +54 -19
  67. package/packages/builtin-tool-knowledge-base/package.json +1 -0
  68. package/packages/builtin-tool-knowledge-base/src/client/Inspector/ReadKnowledge/index.tsx +97 -0
  69. package/packages/builtin-tool-knowledge-base/src/client/Inspector/SearchKnowledgeBase/index.tsx +75 -0
  70. package/packages/builtin-tool-knowledge-base/src/client/Inspector/index.ts +11 -0
  71. package/packages/builtin-tool-knowledge-base/src/client/Render/ReadKnowledge/FileCard.tsx +12 -12
  72. package/packages/builtin-tool-knowledge-base/src/client/Render/ReadKnowledge/index.tsx +16 -25
  73. package/packages/builtin-tool-knowledge-base/src/client/Render/SearchKnowledgeBase/Item/index.tsx +21 -47
  74. package/packages/builtin-tool-knowledge-base/src/client/Render/SearchKnowledgeBase/index.tsx +19 -31
  75. package/packages/builtin-tool-knowledge-base/src/client/Render/index.ts +0 -5
  76. package/packages/builtin-tool-knowledge-base/src/client/index.ts +5 -1
  77. package/packages/builtin-tool-knowledge-base/src/executor/index.ts +119 -0
  78. package/packages/builtin-tool-local-system/package.json +1 -0
  79. package/packages/builtin-tool-local-system/src/client/Inspector/EditLocalFile/index.tsx +44 -29
  80. package/packages/builtin-tool-local-system/src/client/Inspector/GrepContent/index.tsx +20 -18
  81. package/packages/builtin-tool-local-system/src/client/Inspector/ListLocalFiles/index.tsx +76 -0
  82. package/packages/builtin-tool-local-system/src/client/Inspector/ReadLocalFile/index.tsx +8 -32
  83. package/packages/builtin-tool-local-system/src/client/Inspector/RenameLocalFile/index.tsx +62 -0
  84. package/packages/builtin-tool-local-system/src/client/Inspector/SearchLocalFiles/index.tsx +17 -11
  85. package/packages/builtin-tool-local-system/src/client/Inspector/WriteLocalFile/index.tsx +61 -0
  86. package/packages/builtin-tool-local-system/src/client/Inspector/index.ts +6 -0
  87. package/packages/builtin-tool-local-system/src/client/Render/EditLocalFile/index.tsx +6 -1
  88. package/packages/builtin-tool-local-system/src/client/Render/SearchFiles/SearchQuery/SearchView.tsx +19 -31
  89. package/packages/builtin-tool-local-system/src/client/Render/SearchFiles/SearchQuery/index.tsx +2 -42
  90. package/packages/builtin-tool-local-system/src/client/Render/index.ts +0 -2
  91. package/packages/builtin-tool-local-system/src/client/components/FilePathDisplay.tsx +56 -0
  92. package/packages/builtin-tool-local-system/src/client/components/index.ts +2 -0
  93. package/packages/builtin-tool-local-system/src/executor/index.ts +435 -0
  94. package/packages/builtin-tool-web-browsing/src/client/Inspector/Search/index.tsx +32 -5
  95. package/packages/model-runtime/src/core/contextBuilders/google.test.ts +84 -0
  96. package/packages/model-runtime/src/core/contextBuilders/google.ts +37 -1
  97. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/List/Item/Actions.tsx +4 -13
  98. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/List/Item/index.tsx +23 -29
  99. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/List/Item/useDropdownMenu.tsx +3 -3
  100. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/TopicListContent/ThreadList/ThreadItem/Actions.tsx +4 -13
  101. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/TopicListContent/ThreadList/ThreadItem/index.tsx +10 -18
  102. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/TopicListContent/ThreadList/ThreadItem/useDropdownMenu.tsx +3 -3
  103. package/src/app/[variants]/(main)/community/(detail)/assistant/features/Sidebar/ActionButton/AddAgent.tsx +47 -27
  104. package/src/app/[variants]/(main)/community/(detail)/user/features/UserAgentCard.tsx +4 -3
  105. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/List/Item/Actions.tsx +4 -13
  106. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/List/Item/index.tsx +23 -29
  107. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/List/Item/useDropdownMenu.tsx +3 -3
  108. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/TopicListContent/ThreadList/ThreadItem/Actions.tsx +4 -13
  109. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/TopicListContent/ThreadList/ThreadItem/index.tsx +10 -18
  110. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/TopicListContent/ThreadList/ThreadItem/useDropdownMenu.tsx +3 -3
  111. package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/TopicSelector.tsx +18 -20
  112. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentGroupItem/index.tsx +19 -25
  113. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentItem/index.tsx +21 -26
  114. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/Item/Actions.tsx +4 -13
  115. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/Item/useDropdownMenu.tsx +3 -3
  116. package/src/app/[variants]/(main)/home/_layout/Body/Project/List/Actions.tsx +4 -13
  117. package/src/app/[variants]/(main)/home/_layout/Body/Project/List/Item.tsx +8 -15
  118. package/src/app/[variants]/(main)/home/_layout/Body/Project/List/useDropdownMenu.tsx +3 -3
  119. package/src/app/[variants]/(main)/home/_layout/Header/components/AddButton.tsx +3 -4
  120. package/src/app/[variants]/(main)/page/_layout/Body/List/Item/Actions.tsx +4 -13
  121. package/src/app/[variants]/(main)/page/_layout/Body/List/Item/index.tsx +13 -20
  122. package/src/app/[variants]/(main)/page/_layout/Body/List/Item/useDropdownMenu.tsx +3 -3
  123. package/src/app/[variants]/(main)/resource/(home)/_layout/Body/LibraryList/List/Item/Actions.tsx +4 -13
  124. package/src/app/[variants]/(main)/resource/(home)/_layout/Body/LibraryList/List/Item/index.tsx +16 -23
  125. package/src/app/[variants]/(main)/resource/(home)/_layout/Body/LibraryList/List/Item/useDropdownMenu.tsx +3 -3
  126. package/src/app/[variants]/(main)/resource/library/_layout/Header/LibraryHead.tsx +4 -6
  127. package/src/features/AgentBuilder/TopicSelector.tsx +18 -17
  128. package/src/features/Conversation/ChatItem/style.ts +7 -0
  129. package/src/features/Conversation/Messages/Assistant/Actions/Error.tsx +1 -3
  130. package/src/features/Conversation/Messages/Assistant/Actions/index.tsx +37 -16
  131. package/src/features/Conversation/Messages/AssistantGroup/Actions/index.tsx +36 -17
  132. package/src/features/Conversation/Messages/Supervisor/Actions/index.tsx +36 -17
  133. package/src/features/Conversation/Messages/Task/Actions/Error.tsx +1 -3
  134. package/src/features/Conversation/Messages/Task/Actions/index.tsx +31 -15
  135. package/src/features/Conversation/Messages/User/Actions/index.tsx +1 -1
  136. package/src/features/Conversation/Messages/index.tsx +8 -59
  137. package/src/features/Conversation/components/ShareMessageModal/index.tsx +1 -1
  138. package/src/features/Conversation/hooks/useChatItemContextMenu.tsx +313 -83
  139. package/src/features/NavPanel/components/NavItem.tsx +33 -3
  140. package/src/features/PageEditor/Copilot/TopicSelector/Actions.tsx +6 -14
  141. package/src/features/PageEditor/Copilot/TopicSelector/TopicItem.tsx +1 -0
  142. package/src/features/PageEditor/Copilot/TopicSelector/useDropdownMenu.tsx +6 -3
  143. package/src/features/ResourceManager/components/Explorer/ItemDropdown/DropdownMenu.tsx +12 -35
  144. package/src/features/ResourceManager/components/Explorer/ItemDropdown/useFileItemDropdown.tsx +4 -8
  145. package/src/features/ResourceManager/components/Explorer/ListView/ListItem/index.tsx +162 -160
  146. package/src/features/ResourceManager/components/Explorer/MasonryView/MasonryFileItem/index.tsx +16 -8
  147. package/src/features/ResourceManager/components/Explorer/ToolBar/ActionIconWithChevron.tsx +4 -3
  148. package/src/features/ResourceManager/components/Explorer/ToolBar/BatchActionsDropdown.tsx +6 -12
  149. package/src/features/ResourceManager/components/Explorer/ToolBar/SortDropdown.tsx +8 -8
  150. package/src/features/ResourceManager/components/Explorer/ToolBar/ViewSwitcher.tsx +8 -11
  151. package/src/features/ResourceManager/components/Tree/index.tsx +121 -122
  152. package/src/helpers/toolEngineering/index.ts +1 -1
  153. package/src/layout/GlobalProvider/index.tsx +5 -2
  154. package/src/locales/default/plugin.ts +6 -0
  155. package/src/server/modules/Mecha/AgentToolsEngine/__tests__/index.test.ts +1 -1
  156. package/src/server/modules/Mecha/AgentToolsEngine/index.ts +1 -1
  157. package/src/store/chat/slices/builtinTool/actions/index.ts +1 -11
  158. package/src/store/tool/slices/builtin/executors/index.ts +4 -0
  159. package/src/styles/global.ts +6 -0
  160. package/src/styles/text.ts +1 -1
  161. package/src/tools/executionRuntimes.ts +3 -8
  162. package/src/tools/identifiers.ts +1 -1
  163. package/src/tools/index.ts +1 -1
  164. package/src/tools/inspectors.ts +5 -0
  165. package/src/tools/renders.ts +6 -12
  166. package/packages/builtin-tool-local-system/src/client/Render/RenameLocalFile/index.tsx +0 -37
  167. package/src/features/Conversation/components/ContextMenu.tsx +0 -418
  168. package/src/store/chat/slices/builtinTool/actions/__tests__/localSystem.test.ts +0 -201
  169. package/src/store/chat/slices/builtinTool/actions/knowledgeBase.ts +0 -163
  170. package/src/store/chat/slices/builtinTool/actions/localSystem.ts +0 -241
  171. package/src/tools/knowledge-base/ExecutionRuntime/index.ts +0 -25
  172. package/src/tools/knowledge-base/Render/ReadKnowledge/index.tsx +0 -29
  173. package/src/tools/knowledge-base/Render/SearchKnowledgeBase/index.tsx +0 -29
  174. package/src/tools/knowledge-base/Render/index.ts +0 -7
  175. package/src/tools/knowledge-base/index.ts +0 -12
  176. package/src/tools/local-system/ExecutionRuntime/index.ts +0 -9
  177. package/src/tools/local-system/systemRole.ts +0 -1
@@ -1,4 +1,4 @@
1
- import { Button, Center, Checkbox, Flexbox, Icon } from '@lobehub/ui';
1
+ import { Button, Center, Checkbox, ContextMenuTrigger, Flexbox, Icon } from '@lobehub/ui';
2
2
  import { App, Input } from 'antd';
3
3
  import { createStaticStyles, cssVar, cx } from 'antd-style';
4
4
  import dayjs from 'dayjs';
@@ -23,6 +23,7 @@ import { formatSize } from '@/utils/format';
23
23
  import { isChunkingUnsupported } from '@/utils/isChunkingUnsupported';
24
24
 
25
25
  import DropdownMenu from '../../ItemDropdown/DropdownMenu';
26
+ import { useFileItemDropdown } from '../../ItemDropdown/useFileItemDropdown';
26
27
  import ChunksBadge from './ChunkTag';
27
28
 
28
29
  dayjs.extend(relativeTime);
@@ -37,10 +38,6 @@ const styles = createStaticStyles(({ css }) => {
37
38
 
38
39
  &:hover {
39
40
  background: ${cssVar.colorFillTertiary};
40
-
41
- .file-list-item-hover {
42
- opacity: 1;
43
- }
44
41
  }
45
42
  `,
46
43
 
@@ -58,12 +55,14 @@ const styles = createStaticStyles(({ css }) => {
58
55
  opacity: 0.5;
59
56
  `,
60
57
 
61
- hover: cx(
62
- 'file-list-item-hover',
63
- css`
64
- opacity: 0;
65
- `,
66
- ),
58
+ hover: css`
59
+ opacity: 0;
60
+
61
+ &[data-popup-open],
62
+ .file-list-item-group:hover & {
63
+ opacity: 1;
64
+ }
65
+ `,
67
66
  item: css`
68
67
  padding-block: 0;
69
68
  padding-inline: 0 24px;
@@ -324,169 +323,172 @@ const FileListItem = memo<FileListItemProps>(
324
323
  }
325
324
  }, [pendingRenameItemId, id, isFolder, resourceManagerState]);
326
325
 
326
+ const { menuItems } = useFileItemDropdown({
327
+ fileType,
328
+ filename: name,
329
+ id,
330
+ knowledgeBaseId: resourceManagerState.libraryId,
331
+ onRenameStart: isFolder ? handleRenameStart : undefined,
332
+ sourceType,
333
+ url,
334
+ });
335
+
327
336
  return (
328
- <Flexbox
329
- align={'center'}
330
- className={cx(
331
- styles.container,
332
- selected && styles.selected,
333
- isDragging && styles.dragging,
334
- isOver && styles.dragOver,
335
- )}
336
- data-drop-target-id={id}
337
- data-is-folder={String(isFolder)}
338
- draggable={!!resourceManagerState.libraryId}
339
- height={48}
340
- horizontal
341
- onDragEnd={handleDragEnd}
342
- onDragLeave={handleDragLeave}
343
- onDragOver={handleDragOver}
344
- onDragStart={handleDragStart}
345
- onDrop={handleDrop}
346
- paddingInline={8}
347
- style={{
348
- borderBlockEnd: `1px solid ${cssVar.colorBorderSecondary}`,
349
- }}
350
- >
337
+ <ContextMenuTrigger items={menuItems}>
351
338
  <Flexbox
352
339
  align={'center'}
353
- className={styles.item}
354
- distribution={'space-between'}
355
- flex={1}
340
+ className={cx(
341
+ styles.container,
342
+ 'file-list-item-group',
343
+ selected && styles.selected,
344
+ isDragging && styles.dragging,
345
+ isOver && styles.dragOver,
346
+ )}
347
+ data-drop-target-id={id}
348
+ data-is-folder={String(isFolder)}
349
+ draggable={!!resourceManagerState.libraryId}
350
+ height={48}
356
351
  horizontal
357
- onClick={handleItemClick}
352
+ onDragEnd={handleDragEnd}
353
+ onDragLeave={handleDragLeave}
354
+ onDragOver={handleDragOver}
355
+ onDragStart={handleDragStart}
356
+ onDrop={handleDrop}
357
+ paddingInline={8}
358
+ style={{
359
+ borderBlockEnd: `1px solid ${cssVar.colorBorderSecondary}`,
360
+ }}
358
361
  >
359
- <Flexbox align={'center'} className={styles.nameContainer} horizontal>
360
- <Center
361
- height={48}
362
+ <Flexbox
363
+ align={'center'}
364
+ className={styles.item}
365
+ distribution={'space-between'}
366
+ flex={1}
367
+ horizontal
368
+ onClick={handleItemClick}
369
+ >
370
+ <Flexbox align={'center'} className={styles.nameContainer} horizontal>
371
+ <Center
372
+ height={48}
373
+ onClick={(e) => {
374
+ e.stopPropagation();
375
+
376
+ onSelectedChange(id, !selected, e.shiftKey, index);
377
+ }}
378
+ onPointerDown={(e) => e.stopPropagation()}
379
+ style={{ paddingInline: 4 }}
380
+ >
381
+ <Checkbox checked={selected} />
382
+ </Center>
383
+ <Flexbox
384
+ align={'center'}
385
+ justify={'center'}
386
+ style={{ fontSize: 24, marginInline: 8, width: 24 }}
387
+ >
388
+ {isFolder ? (
389
+ <Icon icon={FolderIcon} size={24} />
390
+ ) : isPage ? (
391
+ emoji ? (
392
+ <span style={{ fontSize: 24 }}>{emoji}</span>
393
+ ) : (
394
+ <Center height={24} width={24}>
395
+ <Icon icon={FileText} size={24} />
396
+ </Center>
397
+ )
398
+ ) : (
399
+ <FileIcon fileName={name} fileType={fileType} size={24} />
400
+ )}
401
+ </Flexbox>
402
+ {isRenaming && isFolder ? (
403
+ <Input
404
+ onBlur={handleRenameConfirm}
405
+ onChange={(e) => setRenamingValue(e.target.value)}
406
+ onClick={(e) => e.stopPropagation()}
407
+ onKeyDown={(e) => {
408
+ if (e.key === 'Enter') {
409
+ e.preventDefault();
410
+ handleRenameConfirm();
411
+ } else if (e.key === 'Escape') {
412
+ e.preventDefault();
413
+ handleRenameCancel();
414
+ }
415
+ }}
416
+ onPointerDown={(e) => e.stopPropagation()}
417
+ ref={inputRef}
418
+ size="small"
419
+ style={{ flex: 1, maxWidth: 400 }}
420
+ value={renamingValue}
421
+ />
422
+ ) : (
423
+ <span className={styles.name}>{name || t('file:pageList.untitled')}</span>
424
+ )}
425
+ </Flexbox>
426
+ <Flexbox
427
+ align={'center'}
428
+ gap={8}
429
+ horizontal
362
430
  onClick={(e) => {
363
431
  e.stopPropagation();
364
-
365
- onSelectedChange(id, !selected, e.shiftKey, index);
366
432
  }}
367
433
  onPointerDown={(e) => e.stopPropagation()}
368
- style={{ paddingInline: 4 }}
369
434
  >
370
- <Checkbox checked={selected} />
371
- </Center>
372
- <Flexbox
373
- align={'center'}
374
- justify={'center'}
375
- style={{ fontSize: 24, marginInline: 8, width: 24 }}
376
- >
377
- {isFolder ? (
378
- <Icon icon={FolderIcon} size={24} />
379
- ) : isPage ? (
380
- emoji ? (
381
- <span style={{ fontSize: 24 }}>{emoji}</span>
435
+ {!isFolder &&
436
+ (fileStoreState.isCreatingFileParseTask ||
437
+ isNull(chunkingStatus) ||
438
+ !chunkingStatus ? (
439
+ <div
440
+ className={fileStoreState.isCreatingFileParseTask ? undefined : styles.hover}
441
+ title={t(
442
+ isSupportedForChunking
443
+ ? 'FileManager.actions.chunkingTooltip'
444
+ : 'FileManager.actions.chunkingUnsupported',
445
+ )}
446
+ >
447
+ <Button
448
+ disabled={!isSupportedForChunking}
449
+ icon={FileBoxIcon}
450
+ loading={fileStoreState.isCreatingFileParseTask}
451
+ onClick={() => {
452
+ fileStoreState.parseFiles([id]);
453
+ }}
454
+ size={'small'}
455
+ type={'text'}
456
+ >
457
+ {t(
458
+ fileStoreState.isCreatingFileParseTask
459
+ ? 'FileManager.actions.createChunkingTask'
460
+ : 'FileManager.actions.chunking',
461
+ )}
462
+ </Button>
463
+ </div>
382
464
  ) : (
383
- <Center height={24} width={24}>
384
- <Icon icon={FileText} size={24} />
385
- </Center>
386
- )
387
- ) : (
388
- <FileIcon fileName={name} fileType={fileType} size={24} />
389
- )}
465
+ <div style={{ cursor: 'default' }}>
466
+ <ChunksBadge
467
+ chunkCount={chunkCount}
468
+ chunkingError={chunkingError}
469
+ chunkingStatus={chunkingStatus}
470
+ embeddingError={embeddingError}
471
+ embeddingStatus={embeddingStatus}
472
+ finishEmbedding={finishEmbedding}
473
+ id={id}
474
+ />
475
+ </div>
476
+ ))}
477
+ <DropdownMenu className={styles.hover} items={menuItems} />
390
478
  </Flexbox>
391
- {isRenaming && isFolder ? (
392
- <Input
393
- onBlur={handleRenameConfirm}
394
- onChange={(e) => setRenamingValue(e.target.value)}
395
- onClick={(e) => e.stopPropagation()}
396
- onKeyDown={(e) => {
397
- if (e.key === 'Enter') {
398
- e.preventDefault();
399
- handleRenameConfirm();
400
- } else if (e.key === 'Escape') {
401
- e.preventDefault();
402
- handleRenameCancel();
403
- }
404
- }}
405
- onPointerDown={(e) => e.stopPropagation()}
406
- ref={inputRef}
407
- size="small"
408
- style={{ flex: 1, maxWidth: 400 }}
409
- value={renamingValue}
410
- />
411
- ) : (
412
- <span className={styles.name}>{name || t('file:pageList.untitled')}</span>
413
- )}
414
- </Flexbox>
415
- <Flexbox
416
- align={'center'}
417
- gap={8}
418
- horizontal
419
- onClick={(e) => {
420
- e.stopPropagation();
421
- }}
422
- onPointerDown={(e) => e.stopPropagation()}
423
- >
424
- {!isFolder &&
425
- (fileStoreState.isCreatingFileParseTask ||
426
- isNull(chunkingStatus) ||
427
- !chunkingStatus ? (
428
- <div
429
- className={fileStoreState.isCreatingFileParseTask ? undefined : styles.hover}
430
- title={t(
431
- isSupportedForChunking
432
- ? 'FileManager.actions.chunkingTooltip'
433
- : 'FileManager.actions.chunkingUnsupported',
434
- )}
435
- >
436
- <Button
437
- disabled={!isSupportedForChunking}
438
- icon={FileBoxIcon}
439
- loading={fileStoreState.isCreatingFileParseTask}
440
- onClick={() => {
441
- fileStoreState.parseFiles([id]);
442
- }}
443
- size={'small'}
444
- type={'text'}
445
- >
446
- {t(
447
- fileStoreState.isCreatingFileParseTask
448
- ? 'FileManager.actions.createChunkingTask'
449
- : 'FileManager.actions.chunking',
450
- )}
451
- </Button>
452
- </div>
453
- ) : (
454
- <div style={{ cursor: 'default' }}>
455
- <ChunksBadge
456
- chunkCount={chunkCount}
457
- chunkingError={chunkingError}
458
- chunkingStatus={chunkingStatus}
459
- embeddingError={embeddingError}
460
- embeddingStatus={embeddingStatus}
461
- finishEmbedding={finishEmbedding}
462
- id={id}
463
- />
464
- </div>
465
- ))}
466
- <div className={styles.hover}>
467
- <DropdownMenu
468
- fileType={fileType}
469
- filename={name}
470
- id={id}
471
- knowledgeBaseId={resourceManagerState.libraryId}
472
- onRenameStart={isFolder ? handleRenameStart : undefined}
473
- sourceType={sourceType}
474
- url={url}
475
- />
476
- </div>
477
479
  </Flexbox>
480
+ {!isDragging && (
481
+ <>
482
+ <Flexbox className={styles.item} width={FILE_DATE_WIDTH}>
483
+ {displayTime}
484
+ </Flexbox>
485
+ <Flexbox className={styles.item} width={FILE_SIZE_WIDTH}>
486
+ {isFolder || isPage ? '-' : formatSize(size)}
487
+ </Flexbox>
488
+ </>
489
+ )}
478
490
  </Flexbox>
479
- {!isDragging && (
480
- <>
481
- <Flexbox className={styles.item} width={FILE_DATE_WIDTH}>
482
- {displayTime}
483
- </Flexbox>
484
- <Flexbox className={styles.item} width={FILE_SIZE_WIDTH}>
485
- {isFolder || isPage ? '-' : formatSize(size)}
486
- </Flexbox>
487
- </>
488
- )}
489
- </Flexbox>
491
+ </ContextMenuTrigger>
490
492
  );
491
493
  },
492
494
  );
@@ -1,4 +1,4 @@
1
- import { Checkbox } from '@lobehub/ui';
1
+ import { Checkbox, showContextMenu } from '@lobehub/ui';
2
2
  import { createStaticStyles, cssVar, cx } from 'antd-style';
3
3
  import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
4
  import { useNavigate, useSearchParams } from 'react-router-dom';
@@ -13,6 +13,7 @@ import { documentService } from '@/services/document';
13
13
  import { type FileListItem } from '@/types/files';
14
14
 
15
15
  import DropdownMenu from '../../ItemDropdown/DropdownMenu';
16
+ import { useFileItemDropdown } from '../../ItemDropdown/useFileItemDropdown';
16
17
  import DefaultFileItem from './DefaultFileItem';
17
18
  import ImageFileItem from './ImageFileItem';
18
19
  import MarkdownFileItem from './MarkdownFileItem';
@@ -346,6 +347,15 @@ const MasonryFileItem = memo<MasonryFileItemProps>(
346
347
  }
347
348
  }, [isMarkdown, isPage, url, isInView, markdownContent, id]);
348
349
 
350
+ const { menuItems } = useFileItemDropdown({
351
+ fileType,
352
+ filename: name,
353
+ id,
354
+ knowledgeBaseId,
355
+ sourceType,
356
+ url,
357
+ });
358
+
349
359
  return (
350
360
  <div
351
361
  className={cx(
@@ -357,6 +367,10 @@ const MasonryFileItem = memo<MasonryFileItemProps>(
357
367
  data-drop-target-id={id}
358
368
  data-is-folder={isFolder}
359
369
  draggable={!!knowledgeBaseId}
370
+ onContextMenu={(e) => {
371
+ e.preventDefault();
372
+ showContextMenu(menuItems());
373
+ }}
360
374
  onDragEnd={handleDragEnd}
361
375
  onDragLeave={handleDragLeave}
362
376
  onDragOver={handleDragOver}
@@ -379,13 +393,7 @@ const MasonryFileItem = memo<MasonryFileItemProps>(
379
393
  onClick={(e) => e.stopPropagation()}
380
394
  onPointerDown={(e) => e.stopPropagation()}
381
395
  >
382
- <DropdownMenu
383
- fileType={fileType}
384
- filename={name}
385
- id={id}
386
- knowledgeBaseId={knowledgeBaseId}
387
- url={url}
388
- />
396
+ <DropdownMenu items={menuItems} />
389
397
  </div>
390
398
 
391
399
  <div
@@ -10,14 +10,15 @@ interface ActionIconWithChevronProps extends ComponentProps<typeof Button> {
10
10
  }
11
11
 
12
12
  const ActionIconWithChevron = memo<ActionIconWithChevronProps>(
13
- ({ icon, title, style, disabled, type = 'text', ...rest }) => {
13
+ ({ icon, title, style, disabled, className, ...rest }) => {
14
14
  return (
15
15
  <Button
16
+ {...rest}
17
+ className={className}
16
18
  disabled={disabled}
17
19
  style={{ paddingInline: 4, ...style }}
18
20
  title={title}
19
- type={type}
20
- {...rest}
21
+ type={'text'}
21
22
  >
22
23
  <Flexbox align={'center'} gap={4} horizontal>
23
24
  <Icon color={cssVar.colorIcon} icon={icon} size={18} />
@@ -1,6 +1,5 @@
1
- import { Icon } from '@lobehub/ui';
2
- import { App, Dropdown } from 'antd';
3
- import type { MenuProps } from 'antd';
1
+ import { type DropdownItem, DropdownMenu, Icon } from '@lobehub/ui';
2
+ import { App } from 'antd';
4
3
  import {
5
4
  BookMinusIcon,
6
5
  BookPlusIcon,
@@ -36,8 +35,8 @@ const BatchActionsDropdown = memo<BatchActionsDropdownProps>(
36
35
 
37
36
  const libraryId = useResourceManagerStore((s) => s.libraryId);
38
37
 
39
- const menuItems = useMemo<MenuProps['items']>(() => {
40
- const items: MenuProps['items'] = [];
38
+ const menuItems = useMemo<DropdownItem[]>(() => {
39
+ const items: DropdownItem[] = [];
41
40
 
42
41
  // Show delete library option only when in a knowledge base and no files selected
43
42
  if (libraryId && selectCount === 0) {
@@ -138,18 +137,13 @@ const BatchActionsDropdown = memo<BatchActionsDropdownProps>(
138
137
  }, [libraryId, selectCount, onActionClick, t, modal, message]);
139
138
 
140
139
  return (
141
- <Dropdown
142
- disabled={disabled}
143
- menu={{ items: menuItems }}
144
- placement="bottomLeft"
145
- trigger={['click']}
146
- >
140
+ <DropdownMenu items={menuItems} placement="bottomLeft" triggerProps={{ disabled }}>
147
141
  <ActionIconWithChevron
148
142
  disabled={disabled}
149
143
  icon={CircleEllipsisIcon}
150
144
  title={t('FileManager.actions.batchActions', 'Batch actions')}
151
145
  />
152
- </Dropdown>
146
+ </DropdownMenu>
153
147
  );
154
148
  },
155
149
  );
@@ -1,5 +1,4 @@
1
- import { Dropdown } from 'antd';
2
- import type { MenuProps } from 'antd';
1
+ import { type DropdownItem, DropdownMenu } from '@lobehub/ui';
3
2
  import { ArrowDownAZ } from 'lucide-react';
4
3
  import { memo, useMemo } from 'react';
5
4
  import { useTranslation } from 'react-i18next';
@@ -22,22 +21,23 @@ const SortDropdown = memo(() => {
22
21
  [t],
23
22
  );
24
23
 
25
- const menuItems: MenuProps['items'] = sortOptions.map((option) => ({
24
+ const menuItems: DropdownItem[] = sortOptions.map((option) => ({
26
25
  key: option.key,
27
26
  label: option.label,
28
27
  onClick: () => setSorter(option.key as 'name' | 'createdAt' | 'size'),
28
+ style:
29
+ option.key === (sorter || 'createdAt')
30
+ ? { backgroundColor: 'var(--ant-control-item-bg-active)' }
31
+ : {},
29
32
  }));
30
33
 
31
34
  const currentSortLabel =
32
35
  sortOptions.find((option) => option.key === sorter)?.label || t('FileManager.sort.dateAdded');
33
36
 
34
37
  return (
35
- <Dropdown
36
- menu={{ items: menuItems, selectedKeys: [sorter || 'createdAt'] }}
37
- trigger={['click']}
38
- >
38
+ <DropdownMenu items={menuItems}>
39
39
  <ActionIconWithChevron icon={ArrowDownAZ} title={currentSortLabel} />
40
- </Dropdown>
40
+ </DropdownMenu>
41
41
  );
42
42
  });
43
43
 
@@ -1,6 +1,4 @@
1
- import { Icon } from '@lobehub/ui';
2
- import { Dropdown } from 'antd';
3
- import type { MenuProps } from 'antd';
1
+ import { type DropdownItem, DropdownMenu, Icon } from '@lobehub/ui';
4
2
  import { Grid3x3Icon, ListIcon } from 'lucide-react';
5
3
  import { memo, useMemo } from 'react';
6
4
  import { useTranslation } from 'react-i18next';
@@ -20,31 +18,30 @@ const ViewSwitcher = memo(() => {
20
18
  const currentViewLabel =
21
19
  viewMode === 'list' ? t('FileManager.view.list') : t('FileManager.view.masonry');
22
20
 
23
- const menuItems = useMemo<MenuProps['items']>(() => {
21
+ const menuItems = useMemo<DropdownItem[]>(() => {
24
22
  return [
25
23
  {
26
24
  icon: <Icon icon={ListIcon} />,
27
25
  key: 'list',
28
26
  label: t('FileManager.view.list'),
29
27
  onClick: () => setViewMode('list'),
28
+ style: viewMode === 'list' ? { backgroundColor: 'var(--ant-control-item-bg-active)' } : {},
30
29
  },
31
30
  {
32
31
  icon: <Icon icon={Grid3x3Icon} />,
33
32
  key: 'masonry',
34
33
  label: t('FileManager.view.masonry'),
35
34
  onClick: () => setViewMode('masonry'),
35
+ style:
36
+ viewMode === 'masonry' ? { backgroundColor: 'var(--ant-control-item-bg-active)' } : {},
36
37
  },
37
38
  ];
38
- }, [setViewMode, t]);
39
+ }, [setViewMode, t, viewMode]);
39
40
 
40
41
  return (
41
- <Dropdown
42
- menu={{ items: menuItems, selectedKeys: [viewMode] }}
43
- placement="bottomRight"
44
- trigger={['click']}
45
- >
42
+ <DropdownMenu items={menuItems} placement="bottomRight">
46
43
  <ActionIconWithChevron icon={currentViewIcon} title={currentViewLabel} />
47
- </Dropdown>
44
+ </DropdownMenu>
48
45
  );
49
46
  });
50
47