@lobehub/lobehub 2.0.0-next.297 → 2.0.0-next.299

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 (88) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/changelog/v1.json +18 -0
  3. package/package.json +2 -2
  4. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Cron/Actions.tsx +4 -13
  5. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/Actions.tsx +4 -13
  6. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/index.tsx +2 -9
  7. package/src/app/[variants]/(main)/agent/features/Conversation/ConversationArea.tsx +2 -2
  8. package/src/app/[variants]/(main)/agent/features/Conversation/Header/Tags/KnowledgeTag.tsx +3 -4
  9. package/src/app/[variants]/(main)/agent/profile/features/ProfileEditor/MentionList/types.ts +4 -2
  10. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Nav.tsx +0 -1
  11. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Related/index.tsx +9 -5
  12. package/src/app/[variants]/(main)/community/(detail)/model/features/Sidebar/ActionButton/ChatWithModel.tsx +3 -8
  13. package/src/app/[variants]/(main)/community/(list)/assistant/features/MarketSourceSwitch.tsx +44 -23
  14. package/src/app/[variants]/(main)/community/(list)/features/SortButton/index.tsx +40 -19
  15. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/Actions.tsx +4 -13
  16. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/index.tsx +2 -9
  17. package/src/app/[variants]/(main)/group/features/Conversation/ConversationArea.tsx +2 -2
  18. package/src/app/[variants]/(main)/group/features/Conversation/Header/Tags/KnowledgeTag.tsx +3 -4
  19. package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/AgentBuilderProvider.tsx +2 -2
  20. package/src/app/[variants]/(main)/group/profile/features/MemberProfile/MentionList/types.ts +4 -2
  21. package/src/app/[variants]/(main)/home/_layout/Body/Agent/Actions.tsx +3 -11
  22. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/Group/Actions.tsx +3 -12
  23. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/Group/Item.tsx +2 -9
  24. package/src/app/[variants]/(main)/home/_layout/Body/Agent/index.tsx +2 -9
  25. package/src/app/[variants]/(main)/home/_layout/Body/Project/index.tsx +2 -9
  26. package/src/app/[variants]/(main)/home/_layout/HomeAgentIdSync.tsx +23 -0
  27. package/src/app/[variants]/(main)/home/_layout/index.tsx +2 -0
  28. package/src/app/[variants]/(main)/home/features/CommunityAgents/index.tsx +11 -13
  29. package/src/app/[variants]/(main)/home/features/FeaturedPlugins/index.tsx +11 -13
  30. package/src/app/[variants]/(main)/home/features/RecentPage/index.tsx +12 -14
  31. package/src/app/[variants]/(main)/home/features/RecentResource/index.tsx +12 -14
  32. package/src/app/[variants]/(main)/memory/contexts/features/ContextDropdown.tsx +5 -3
  33. package/src/app/[variants]/(main)/memory/experiences/features/ExperienceDropdown.tsx +5 -3
  34. package/src/app/[variants]/(main)/memory/identities/features/IdentityDropdown.tsx +5 -3
  35. package/src/app/[variants]/(main)/memory/preferences/features/PreferenceDropdown.tsx +5 -3
  36. package/src/app/[variants]/(main)/page/_layout/Body/Actions.tsx +3 -13
  37. package/src/app/[variants]/(main)/page/_layout/Body/index.tsx +2 -9
  38. package/src/app/[variants]/(main)/resource/features/DndContextWrapper.tsx +1 -1
  39. package/src/app/[variants]/(main)/settings/profile/features/SSOProvidersList/index.tsx +3 -3
  40. package/src/app/[variants]/(main)/settings/provider/ProviderMenu/Actions.tsx +3 -11
  41. package/src/app/[variants]/(main)/settings/provider/ProviderMenu/List.tsx +12 -28
  42. package/src/app/[variants]/(main)/settings/provider/features/ModelList/DisabledModels.tsx +7 -8
  43. package/src/app/[variants]/(main)/settings/provider/features/ModelList/ModelTitle/index.tsx +18 -20
  44. package/src/app/[variants]/(mobile)/(home)/features/SessionListContent/CollapseGroup/Actions.tsx +10 -14
  45. package/src/app/[variants]/(mobile)/(home)/features/SessionListContent/List/Item/Actions.tsx +3 -13
  46. package/src/app/[variants]/share/t/[id]/SharedMessageList.tsx +2 -2
  47. package/src/business/server/lambda-routers/file.ts +1 -1
  48. package/src/features/AgentBuilder/AgentBuilderProvider.tsx +2 -2
  49. package/src/features/ChatInput/ActionBar/History/index.tsx +1 -1
  50. package/src/features/ChatInput/ActionBar/STT/common.tsx +1 -1
  51. package/src/features/ChatInput/ActionBar/Search/index.tsx +1 -1
  52. package/src/features/ChatInput/ActionBar/Upload/ServerMode.tsx +1 -0
  53. package/src/features/ChatInput/ActionBar/components/Action.tsx +4 -8
  54. package/src/features/ChatInput/ActionBar/components/ActionDropdown.tsx +225 -37
  55. package/src/features/Conversation/ConversationProvider.tsx +2 -1
  56. package/src/features/Conversation/Messages/Assistant/Actions/index.tsx +10 -6
  57. package/src/features/Conversation/Messages/AssistantGroup/Actions/index.tsx +10 -6
  58. package/src/features/Conversation/Messages/AssistantGroup/Tool/Detail/Intervention/ApprovalActions.tsx +11 -13
  59. package/src/features/Conversation/Messages/AssistantGroup/Tool/Detail/Intervention/ModeSelector.tsx +8 -10
  60. package/src/features/Conversation/Messages/Supervisor/Actions/index.tsx +10 -6
  61. package/src/features/Conversation/Messages/Task/Actions/index.tsx +10 -6
  62. package/src/features/Conversation/Messages/User/Actions/index.tsx +10 -6
  63. package/src/features/Conversation/StoreUpdater.tsx +1 -1
  64. package/src/features/Conversation/store/initialState.ts +3 -1
  65. package/src/features/Conversation/store/slices/data/action.ts +6 -5
  66. package/src/features/LibraryModal/AssignKnowledgeBase/Item/Action.tsx +23 -26
  67. package/src/features/ModelSwitchPanel/components/List/MultipleProvidersModelItem.tsx +16 -18
  68. package/src/features/ModelSwitchPanel/styles.ts +18 -1
  69. package/src/features/PageEditor/Copilot/AgentSelector/Actions.tsx +6 -13
  70. package/src/features/PageEditor/PageAgentProvider.tsx +2 -2
  71. package/src/features/PluginStore/InstalledList/List/Item/Action.tsx +33 -36
  72. package/src/features/PluginStore/McpList/List/Action.tsx +25 -28
  73. package/src/features/PluginStore/PluginList/List/Action.tsx +25 -28
  74. package/src/features/PluginTag/index.tsx +3 -4
  75. package/src/features/Portal/Artifacts/Body/Renderer/SVG.tsx +14 -11
  76. package/src/features/Portal/Thread/Chat/index.tsx +2 -2
  77. package/src/features/ProfileEditor/AgentTool.tsx +1 -1
  78. package/src/features/ResourceManager/components/Explorer/ToolBar/SortDropdown.tsx +21 -18
  79. package/src/features/ResourceManager/components/Explorer/ToolBar/ViewSwitcher.tsx +7 -13
  80. package/src/features/ResourceManager/components/Header/AddButton.tsx +4 -11
  81. package/src/features/User/UserPanel/LangButton.tsx +56 -44
  82. package/src/layout/AuthProvider/MarketAuth/MarketAuthProvider.tsx +1 -1
  83. package/src/services/discover.ts +6 -4
  84. package/src/services/document/index.ts +11 -1
  85. package/src/store/page/slices/crud/action.ts +0 -48
  86. package/src/store/tool/slices/lobehubSkillStore/action.ts +1 -2
  87. package/src/styles/global.ts +2 -2
  88. package/src/types/shim-lobe-ui.d.ts +7 -0
@@ -1,4 +1,4 @@
1
- import { Button, Dropdown, Flexbox, Popover } from '@lobehub/ui';
1
+ import { Button, DropdownMenu, Flexbox, Popover } from '@lobehub/ui';
2
2
  import { Input, Space } from 'antd';
3
3
  import { ChevronDown } from 'lucide-react';
4
4
  import { memo, useState } from 'react';
@@ -140,17 +140,15 @@ const ApprovalActions = memo<ApprovalActionsProps>(
140
140
  >
141
141
  {t('tool.intervention.approveAndRemember')}
142
142
  </Button>
143
- <Dropdown
144
- menu={{
145
- items: [
146
- {
147
- disabled: approveLoading || isMessageCreating,
148
- key: 'once',
149
- label: t('tool.intervention.approveOnce'),
150
- onClick: () => handleApprove(false),
151
- },
152
- ],
153
- }}
143
+ <DropdownMenu
144
+ items={[
145
+ {
146
+ disabled: approveLoading || isMessageCreating,
147
+ key: 'once',
148
+ label: t('tool.intervention.approveOnce'),
149
+ onClick: () => handleApprove(false),
150
+ },
151
+ ]}
154
152
  >
155
153
  <Button
156
154
  disabled={approveLoading || isMessageCreating}
@@ -158,7 +156,7 @@ const ApprovalActions = memo<ApprovalActionsProps>(
158
156
  size="small"
159
157
  type="primary"
160
158
  />
161
- </Dropdown>
159
+ </DropdownMenu>
162
160
  </Space.Compact>
163
161
  ) : (
164
162
  <Button
@@ -1,7 +1,6 @@
1
- import { Button, Dropdown, Icon, type MenuProps } from '@lobehub/ui';
2
- import { Center } from '@lobehub/ui';
1
+ import { Button, Center, DropdownMenu, Icon, type MenuProps } from '@lobehub/ui';
3
2
  import { createStaticStyles } from 'antd-style';
4
- import { ChevronDown, Hand, ListChecks, Zap } from 'lucide-react';
3
+ import { Check, ChevronDown, Hand, ListChecks, Zap } from 'lucide-react';
5
4
  import { memo, useCallback, useMemo } from 'react';
6
5
  import { useTranslation } from 'react-i18next';
7
6
 
@@ -61,6 +60,7 @@ const ModeSelector = memo(() => {
61
60
  const menuItems = useMemo<MenuProps['items']>(
62
61
  () => [
63
62
  {
63
+ extra: approvalMode === 'auto-run' ? <Icon icon={Check} /> : undefined,
64
64
  icon: (
65
65
  <Center className={styles.icon} height={32} width={32}>
66
66
  <Icon icon={Zap} />
@@ -76,6 +76,7 @@ const ModeSelector = memo(() => {
76
76
  onClick: () => handleModeChange('auto-run'),
77
77
  },
78
78
  {
79
+ extra: approvalMode === 'allow-list' ? <Icon icon={Check} /> : undefined,
79
80
  icon: (
80
81
  <Center className={styles.icon} height={32} width={32}>
81
82
  <Icon icon={ListChecks} />
@@ -91,6 +92,7 @@ const ModeSelector = memo(() => {
91
92
  onClick: () => handleModeChange('allow-list'),
92
93
  },
93
94
  {
95
+ extra: approvalMode === 'manual' ? <Icon icon={Check} /> : undefined,
94
96
  icon: (
95
97
  <Center className={styles.icon} height={32} width={32}>
96
98
  <Icon icon={Hand} />
@@ -106,15 +108,11 @@ const ModeSelector = memo(() => {
106
108
  onClick: () => handleModeChange('manual'),
107
109
  },
108
110
  ],
109
- [modeLabels, handleModeChange, styles, t],
111
+ [approvalMode, modeLabels, handleModeChange, styles, t],
110
112
  );
111
113
 
112
114
  return (
113
- <Dropdown
114
- // @ts-expect-error activeKey 没在 Dropdown key 里很奇怪
115
- menu={{ activeKey: approvalMode, items: menuItems }}
116
- placement="bottomLeft"
117
- >
115
+ <DropdownMenu items={menuItems} placement="bottomLeft">
118
116
  <Button
119
117
  className={styles.modeButton}
120
118
  color={'default'}
@@ -125,7 +123,7 @@ const ModeSelector = memo(() => {
125
123
  >
126
124
  {modeLabels[approvalMode]}
127
125
  </Button>
128
- </Dropdown>
126
+ </DropdownMenu>
129
127
  );
130
128
  });
131
129
 
@@ -21,16 +21,20 @@ import { useGroupActions } from './useGroupActions';
21
21
  // Helper to strip handleClick from action items before passing to ActionIconGroup
22
22
  const stripHandleClick = (item: MessageActionItemOrDivider): ActionIconGroupItemType => {
23
23
  if ('type' in item && item.type === 'divider') return item as unknown as ActionIconGroupItemType;
24
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
25
- const { handleClick, children, ...rest } = item as MessageActionItem;
24
+ const { children, ...rest } = item as MessageActionItem;
25
+ const baseItem = { ...rest } as MessageActionItem;
26
+ delete (baseItem as { handleClick?: unknown }).handleClick;
26
27
  if (children) {
27
28
  return {
28
- ...rest,
29
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
30
- children: children.map(({ handleClick: _, ...child }) => child),
29
+ ...baseItem,
30
+ children: children.map((child) => {
31
+ const nextChild = { ...child } as MessageActionItem;
32
+ delete (nextChild as { handleClick?: unknown }).handleClick;
33
+ return nextChild;
34
+ }),
31
35
  } as ActionIconGroupItemType;
32
36
  }
33
- return rest as ActionIconGroupItemType;
37
+ return baseItem as ActionIconGroupItemType;
34
38
  };
35
39
 
36
40
  // Build action items map for handleAction lookup
@@ -18,16 +18,20 @@ import { useAssistantActions } from './useAssistantActions';
18
18
  // Helper to strip handleClick from action items before passing to ActionIconGroup
19
19
  const stripHandleClick = (item: MessageActionItemOrDivider): ActionIconGroupItemType => {
20
20
  if ('type' in item && item.type === 'divider') return item as unknown as ActionIconGroupItemType;
21
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
22
- const { handleClick, children, ...rest } = item as MessageActionItem;
21
+ const { children, ...rest } = item as MessageActionItem;
22
+ const baseItem = { ...rest } as MessageActionItem;
23
+ delete (baseItem as { handleClick?: unknown }).handleClick;
23
24
  if (children) {
24
25
  return {
25
- ...rest,
26
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
27
- children: children.map(({ handleClick: _, ...child }) => child),
26
+ ...baseItem,
27
+ children: children.map((child) => {
28
+ const nextChild = { ...child } as MessageActionItem;
29
+ delete (nextChild as { handleClick?: unknown }).handleClick;
30
+ return nextChild;
31
+ }),
28
32
  } as ActionIconGroupItemType;
29
33
  }
30
- return rest as ActionIconGroupItemType;
34
+ return baseItem as ActionIconGroupItemType;
31
35
  };
32
36
 
33
37
  // Build action items map for handleAction lookup
@@ -16,16 +16,20 @@ import { useUserActions } from './useUserActions';
16
16
  // Helper to strip handleClick from action items before passing to ActionIconGroup
17
17
  const stripHandleClick = (item: MessageActionItemOrDivider): ActionIconGroupItemType => {
18
18
  if ('type' in item && item.type === 'divider') return item as unknown as ActionIconGroupItemType;
19
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
20
- const { handleClick, children, ...rest } = item as MessageActionItem;
19
+ const { children, ...rest } = item as MessageActionItem;
20
+ const baseItem = { ...rest } as MessageActionItem;
21
+ delete (baseItem as { handleClick?: unknown }).handleClick;
21
22
  if (children) {
22
23
  return {
23
- ...rest,
24
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
25
- children: children.map(({ handleClick: _, ...child }) => child),
24
+ ...baseItem,
25
+ children: children.map((child) => {
26
+ const nextChild = { ...child } as MessageActionItem;
27
+ delete (nextChild as { handleClick?: unknown }).handleClick;
28
+ return nextChild;
29
+ }),
26
30
  } as ActionIconGroupItemType;
27
31
  }
28
- return rest as ActionIconGroupItemType;
32
+ return baseItem as ActionIconGroupItemType;
29
33
  };
30
34
 
31
35
  // Build action items map for handleAction lookup
@@ -30,7 +30,7 @@ export interface StoreUpdaterProps {
30
30
  /**
31
31
  * Callback when messages are fetched or changed internally
32
32
  */
33
- onMessagesChange?: (messages: UIChatMessage[]) => void;
33
+ onMessagesChange?: (messages: UIChatMessage[], context: ConversationContext) => void;
34
34
  /**
35
35
  * External operation state (from ChatStore)
36
36
  */
@@ -33,8 +33,10 @@ export interface State extends DataState, InputState, MessageStateState, VirtuaL
33
33
 
34
34
  /**
35
35
  * Callback when messages are fetched or changed internally
36
+ * @param messages - The updated messages array
37
+ * @param context - The context that this data belongs to (prevents race conditions)
36
38
  */
37
- onMessagesChange?: (messages: UIChatMessage[]) => void;
39
+ onMessagesChange?: (messages: UIChatMessage[], context: ConversationContext) => void;
38
40
 
39
41
  /**
40
42
  * External operation state (from ChatStore)
@@ -74,7 +74,7 @@ export const dataSlice: StateCreator<
74
74
  });
75
75
 
76
76
  // Sync changes to external store (ChatStore)
77
- get().onMessagesChange?.(newDbMessages);
77
+ get().onMessagesChange?.(newDbMessages, get().context);
78
78
  },
79
79
 
80
80
  replaceMessages: (messages) => {
@@ -84,7 +84,7 @@ export const dataSlice: StateCreator<
84
84
  set({ dbMessages: messages, displayMessages: flatList }, false, 'replaceMessages');
85
85
 
86
86
  // Sync changes to external store (ChatStore)
87
- get().onMessagesChange?.(messages);
87
+ get().onMessagesChange?.(messages, get().context);
88
88
  },
89
89
 
90
90
  switchMessageBranch: async (messageId, branchIndex) => {
@@ -106,7 +106,6 @@ export const dataSlice: StateCreator<
106
106
  // Also skip fetch when topicId is null (new conversation state) - there's no server data,
107
107
  // only local optimistic updates. Fetching would return empty array and overwrite local data.
108
108
  const shouldFetch = !skipFetch && !!context.agentId && !!context.topicId;
109
-
110
109
  return useClientDataSWRWithSync<UIChatMessage[]>(
111
110
  shouldFetch ? ['CONVERSATION_FETCH_MESSAGES', context] : null,
112
111
 
@@ -116,6 +115,7 @@ export const dataSlice: StateCreator<
116
115
  {
117
116
  onData: (data) => {
118
117
  if (!data) return;
118
+ if (!context.topicId) return;
119
119
 
120
120
  // Parse messages using conversation-flow
121
121
  const { flatList } = parse(data);
@@ -126,8 +126,9 @@ export const dataSlice: StateCreator<
126
126
  messagesInit: true,
127
127
  });
128
128
 
129
- // Call onMessagesChange callback if provided
130
- get().onMessagesChange?.(data);
129
+ // Call onMessagesChange callback with the request context (not current context)
130
+ // This ensures data is stored to the correct topic even if user switched topics
131
+ get().onMessagesChange?.(data, context);
131
132
  },
132
133
  },
133
134
  );
@@ -1,4 +1,4 @@
1
- import { ActionIcon, Button, Dropdown, Flexbox, Icon } from '@lobehub/ui';
1
+ import { ActionIcon, Button, DropdownMenu, Flexbox, Icon } from '@lobehub/ui';
2
2
  import { InfoIcon, MoreVerticalIcon, Trash2 } from 'lucide-react';
3
3
  import { memo, useState } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
@@ -54,36 +54,33 @@ const Actions = memo<ActionsProps>(({ id, type, enabled }) => {
54
54
  return (
55
55
  <Flexbox align={'center'} horizontal>
56
56
  {enabled ? (
57
- <Dropdown
58
- menu={{
59
- items: [
60
- {
61
- icon: <Icon icon={InfoIcon} />,
62
- key: 'detail',
63
- label: t('knowledgeBase.library.action.detail'),
64
- onClick: () => {
65
- if (type === KnowledgeType.KnowledgeBase) {
66
- window.open(`/resource/library/${id}`);
67
- return;
68
- }
57
+ <DropdownMenu
58
+ items={[
59
+ {
60
+ icon: <Icon icon={InfoIcon} />,
61
+ key: 'detail',
62
+ label: t('knowledgeBase.library.action.detail'),
63
+ onClick: () => {
64
+ if (type === KnowledgeType.KnowledgeBase) {
65
+ window.open(`/resource/library/${id}`);
66
+ return;
67
+ }
69
68
 
70
- window.open(`/knowledge?file=${id}`);
71
- },
69
+ window.open(`/knowledge?file=${id}`);
72
70
  },
73
- {
74
- danger: true,
75
- icon: <Icon icon={Trash2} />,
76
- key: 'remove',
77
- label: t('knowledgeBase.library.action.remove'),
78
- onClick: removeKnowledge,
79
- },
80
- ],
81
- }}
71
+ },
72
+ {
73
+ danger: true,
74
+ icon: <Icon icon={Trash2} />,
75
+ key: 'remove',
76
+ label: t('knowledgeBase.library.action.remove'),
77
+ onClick: removeKnowledge,
78
+ },
79
+ ]}
82
80
  placement="bottomRight"
83
- trigger={['click']}
84
81
  >
85
82
  <ActionIcon icon={MoreVerticalIcon} loading={loading} />
86
- </Dropdown>
83
+ </DropdownMenu>
87
84
  ) : (
88
85
  <Button
89
86
  loading={loading}
@@ -1,6 +1,5 @@
1
- import { ActionIcon, Dropdown } from '@lobehub/ui';
2
- import { MenuItemType } from 'antd/es/menu/interface';
3
- import { LucideBolt } from 'lucide-react';
1
+ import { ActionIcon, type DropdownItem, DropdownMenu } from '@lobehub/ui';
2
+ import { Check, LucideBolt } from 'lucide-react';
4
3
  import { memo, useMemo } from 'react';
5
4
  import { useTranslation } from 'react-i18next';
6
5
  import { useNavigate } from 'react-router-dom';
@@ -34,6 +33,8 @@ export const MultipleProvidersModelItem = memo<MultipleProvidersModelItemProps>(
34
33
  type: 'group',
35
34
  },
36
35
  ...data.providers.map((p) => {
36
+ const key = menuKey(p.id, data.model.id);
37
+
37
38
  return {
38
39
  extra: (
39
40
  <ActionIcon
@@ -53,7 +54,8 @@ export const MultipleProvidersModelItem = memo<MultipleProvidersModelItemProps>(
53
54
  title={t('ModelSwitchPanel.goToSettings')}
54
55
  />
55
56
  ),
56
- key: menuKey(p.id, data.model.id),
57
+ icon: activeKey === key ? Check : undefined,
58
+ key,
57
59
  label: (
58
60
  <ProviderItemRender
59
61
  logo={p.logo}
@@ -70,23 +72,19 @@ export const MultipleProvidersModelItem = memo<MultipleProvidersModelItemProps>(
70
72
  },
71
73
  };
72
74
  }),
73
- ] as MenuItemType[],
74
- [data.model.id, data.providers, navigate, onModelChange, onClose, t],
75
+ ] as DropdownItem[],
76
+ [activeKey, data.model.id, data.providers, navigate, onModelChange, onClose, t],
75
77
  );
76
78
 
77
79
  return (
78
- <Dropdown
79
- align={{ offset: [12, -48] }}
80
- arrow={false}
81
- classNames={{
82
- item: styles.menuItem,
83
- }}
84
- menu={{
85
- items,
86
- selectedKeys: [activeKey],
87
- }}
88
- // @ts-ignore
80
+ <DropdownMenu
81
+ items={items}
89
82
  placement="rightTop"
83
+ popupProps={{ className: styles.dropdownMenu }}
84
+ positionerProps={{
85
+ alignOffset: -48,
86
+ sideOffset: 12,
87
+ }}
90
88
  >
91
89
  <ModelItemRender
92
90
  {...data.model}
@@ -95,7 +93,7 @@ export const MultipleProvidersModelItem = memo<MultipleProvidersModelItemProps>(
95
93
  newBadgeLabel={newLabel}
96
94
  showInfoTag={true}
97
95
  />
98
- </Dropdown>
96
+ </DropdownMenu>
99
97
  );
100
98
  },
101
99
  );
@@ -5,10 +5,27 @@ export const styles = createStaticStyles(({ css, cssVar }) => ({
5
5
  overflow: hidden;
6
6
  padding: 0 !important;
7
7
  `,
8
+ dropdownMenu: css`
9
+ [role='menuitem'] {
10
+ margin-block: 1px;
11
+ margin-inline: 4px;
12
+ padding-block: 8px;
13
+ padding-inline: 8px;
14
+ border-radius: ${cssVar.borderRadiusSM};
15
+ }
16
+
17
+ [role='menuitem'] .settings-icon {
18
+ opacity: 0;
19
+ }
20
+
21
+ [role='menuitem']:hover .settings-icon {
22
+ opacity: 1;
23
+ }
24
+ `,
25
+
8
26
  footer: css`
9
27
  border-block-start: 1px solid ${cssVar.colorBorderSecondary};
10
28
  `,
11
-
12
29
  groupHeader: css`
13
30
  width: 100%;
14
31
  color: ${cssVar.colorTextSecondary};
@@ -1,4 +1,4 @@
1
- import { ActionIcon, Dropdown, type MenuProps } from '@lobehub/ui';
1
+ import { ActionIcon, DropdownMenu, type MenuProps } from '@lobehub/ui';
2
2
  import { MoreHorizontalIcon } from 'lucide-react';
3
3
  import { memo } from 'react';
4
4
 
@@ -7,21 +7,14 @@ interface ActionsProps {
7
7
  }
8
8
 
9
9
  const Actions = memo<ActionsProps>(({ dropdownMenu }) => {
10
- if (!dropdownMenu || dropdownMenu.length === 0) return null;
10
+ const menuItems = dropdownMenu ?? [];
11
+
12
+ if (menuItems.length === 0) return null;
11
13
 
12
14
  return (
13
- <Dropdown
14
- arrow={false}
15
- menu={{
16
- items: dropdownMenu,
17
- onClick: ({ domEvent }) => {
18
- domEvent.stopPropagation();
19
- },
20
- }}
21
- trigger={['click']}
22
- >
15
+ <DropdownMenu items={menuItems}>
23
16
  <ActionIcon icon={MoreHorizontalIcon} size={'small'} />
24
- </Dropdown>
17
+ </DropdownMenu>
25
18
  );
26
19
  });
27
20
 
@@ -49,8 +49,8 @@ const PageAgentProvider = memo<PageAgentProviderProps>(({ pageAgentId, children
49
49
  context={context}
50
50
  hasInitMessages={!!messages}
51
51
  messages={messages}
52
- onMessagesChange={(msgs) => {
53
- replaceMessages(msgs, { context });
52
+ onMessagesChange={(msgs, ctx) => {
53
+ replaceMessages(msgs, { context: ctx });
54
54
  }}
55
55
  operationState={operationState}
56
56
  >
@@ -1,4 +1,4 @@
1
- import { ActionIcon, Button, Dropdown, Flexbox, Icon } from '@lobehub/ui';
1
+ import { ActionIcon, Button, DropdownMenu, Flexbox, Icon } from '@lobehub/ui';
2
2
  import { App } from 'antd';
3
3
  import { InfoIcon, MoreVerticalIcon, PackageSearch, Settings, Trash2 } from 'lucide-react';
4
4
  import { memo, useState } from 'react';
@@ -72,46 +72,43 @@ const Actions = memo<ActionsProps>(({ identifier, type, isMCP }) => {
72
72
  title={t('store.actions.settings')}
73
73
  />
74
74
  )}
75
- <Dropdown
76
- menu={{
77
- items: [
78
- {
79
- icon: <Icon icon={InfoIcon} />,
80
- key: 'detail',
81
- label: t('store.actions.detail'),
82
- onClick: () => {
83
- setOpen(true);
84
- setTab('info');
85
- },
75
+ <DropdownMenu
76
+ items={[
77
+ {
78
+ icon: <Icon icon={InfoIcon} />,
79
+ key: 'detail',
80
+ label: t('store.actions.detail'),
81
+ onClick: () => {
82
+ setOpen(true);
83
+ setTab('info');
86
84
  },
87
- {
88
- danger: true,
89
- icon: <Icon icon={Trash2} />,
90
- key: 'uninstall',
91
- label: t('store.actions.uninstall'),
92
- onClick: () => {
93
- modal.confirm({
94
- centered: true,
95
- okButtonProps: { danger: true },
96
- onOk: async () => {
97
- // If plugin is enabled in current agent, disable it first
98
- if (isPluginEnabledInAgent) {
99
- await togglePlugin(identifier, false);
100
- }
101
- await unInstallPlugin(identifier);
102
- },
103
- title: t('store.actions.confirmUninstall'),
104
- type: 'error',
105
- });
106
- },
85
+ },
86
+ {
87
+ danger: true,
88
+ icon: <Icon icon={Trash2} />,
89
+ key: 'uninstall',
90
+ label: t('store.actions.uninstall'),
91
+ onClick: () => {
92
+ modal.confirm({
93
+ centered: true,
94
+ okButtonProps: { danger: true },
95
+ onOk: async () => {
96
+ // If plugin is enabled in current agent, disable it first
97
+ if (isPluginEnabledInAgent) {
98
+ await togglePlugin(identifier, false);
99
+ }
100
+ await unInstallPlugin(identifier);
101
+ },
102
+ title: t('store.actions.confirmUninstall'),
103
+ type: 'error',
104
+ });
107
105
  },
108
- ],
109
- }}
106
+ },
107
+ ]}
110
108
  placement="bottomRight"
111
- trigger={['click']}
112
109
  >
113
110
  <ActionIcon icon={MoreVerticalIcon} loading={installing} />
114
- </Dropdown>
111
+ </DropdownMenu>
115
112
  </>
116
113
  ) : (
117
114
  <Button
@@ -1,4 +1,4 @@
1
- import { ActionIcon, Button, Dropdown, Flexbox, Icon } from '@lobehub/ui';
1
+ import { ActionIcon, Button, DropdownMenu, Flexbox, Icon } from '@lobehub/ui';
2
2
  import { App } from 'antd';
3
3
  import { MoreVerticalIcon, Trash2 } from 'lucide-react';
4
4
  import { memo } from 'react';
@@ -39,34 +39,31 @@ const Actions = memo<ActionsProps>(({ identifier }) => {
39
39
  return (
40
40
  <Flexbox align={'center'} horizontal>
41
41
  {installed ? (
42
- <Dropdown
43
- menu={{
44
- items: [
45
- {
46
- danger: true,
47
- icon: <Icon icon={Trash2} />,
48
- key: 'uninstall',
49
- label: t('store.actions.uninstall'),
50
- onClick: () => {
51
- modal.confirm({
52
- centered: true,
53
- okButtonProps: { danger: true },
54
- onOk: async () => {
55
- // If plugin is enabled in current agent, disable it first
56
- if (isPluginEnabledInAgent) {
57
- await togglePlugin(identifier, false);
58
- }
59
- await unInstallPlugin(identifier);
60
- },
61
- title: t('store.actions.confirmUninstall'),
62
- type: 'error',
63
- });
64
- },
42
+ <DropdownMenu
43
+ items={[
44
+ {
45
+ danger: true,
46
+ icon: <Icon icon={Trash2} />,
47
+ key: 'uninstall',
48
+ label: t('store.actions.uninstall'),
49
+ onClick: () => {
50
+ modal.confirm({
51
+ centered: true,
52
+ okButtonProps: { danger: true },
53
+ onOk: async () => {
54
+ // If plugin is enabled in current agent, disable it first
55
+ if (isPluginEnabledInAgent) {
56
+ await togglePlugin(identifier, false);
57
+ }
58
+ await unInstallPlugin(identifier);
59
+ },
60
+ title: t('store.actions.confirmUninstall'),
61
+ type: 'error',
62
+ });
65
63
  },
66
- ],
67
- }}
64
+ },
65
+ ]}
68
66
  placement="bottomRight"
69
- trigger={['click']}
70
67
  >
71
68
  <ActionIcon
72
69
  icon={MoreVerticalIcon}
@@ -75,7 +72,7 @@ const Actions = memo<ActionsProps>(({ identifier }) => {
75
72
  e.stopPropagation();
76
73
  }}
77
74
  />
78
- </Dropdown>
75
+ </DropdownMenu>
79
76
  ) : installing ? (
80
77
  <Button
81
78
  onClick={async (e) => {