@lobehub/lobehub 2.0.0-next.273 → 2.0.0-next.274

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 (227) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/changelog/v1.json +9 -0
  3. package/locales/ar/chat.json +7 -0
  4. package/locales/ar/models.json +2 -3
  5. package/locales/ar/plugin.json +22 -1
  6. package/locales/bg-BG/chat.json +7 -0
  7. package/locales/bg-BG/models.json +3 -3
  8. package/locales/bg-BG/plugin.json +22 -1
  9. package/locales/de-DE/chat.json +7 -0
  10. package/locales/de-DE/models.json +3 -4
  11. package/locales/de-DE/plugin.json +22 -1
  12. package/locales/en-US/chat.json +7 -0
  13. package/locales/en-US/models.json +5 -5
  14. package/locales/en-US/plugin.json +22 -1
  15. package/locales/es-ES/chat.json +7 -0
  16. package/locales/es-ES/models.json +3 -4
  17. package/locales/es-ES/plugin.json +22 -1
  18. package/locales/fa-IR/chat.json +7 -0
  19. package/locales/fa-IR/models.json +3 -4
  20. package/locales/fa-IR/plugin.json +22 -1
  21. package/locales/fr-FR/chat.json +7 -0
  22. package/locales/fr-FR/models.json +50 -3
  23. package/locales/fr-FR/plugin.json +22 -1
  24. package/locales/it-IT/chat.json +7 -0
  25. package/locales/it-IT/models.json +3 -3
  26. package/locales/it-IT/plugin.json +22 -1
  27. package/locales/ja-JP/chat.json +7 -0
  28. package/locales/ja-JP/models.json +43 -4
  29. package/locales/ja-JP/plugin.json +22 -1
  30. package/locales/ko-KR/chat.json +7 -0
  31. package/locales/ko-KR/models.json +3 -4
  32. package/locales/ko-KR/plugin.json +22 -1
  33. package/locales/nl-NL/chat.json +7 -0
  34. package/locales/nl-NL/models.json +51 -3
  35. package/locales/nl-NL/plugin.json +22 -1
  36. package/locales/pl-PL/chat.json +7 -0
  37. package/locales/pl-PL/models.json +3 -3
  38. package/locales/pl-PL/plugin.json +22 -1
  39. package/locales/pt-BR/chat.json +7 -0
  40. package/locales/pt-BR/models.json +3 -4
  41. package/locales/pt-BR/plugin.json +22 -1
  42. package/locales/ru-RU/chat.json +7 -0
  43. package/locales/ru-RU/models.json +3 -4
  44. package/locales/ru-RU/plugin.json +22 -1
  45. package/locales/tr-TR/chat.json +7 -0
  46. package/locales/tr-TR/models.json +3 -4
  47. package/locales/tr-TR/plugin.json +22 -1
  48. package/locales/vi-VN/chat.json +7 -0
  49. package/locales/vi-VN/models.json +3 -3
  50. package/locales/vi-VN/plugin.json +22 -1
  51. package/locales/zh-CN/chat.json +7 -0
  52. package/locales/zh-CN/models.json +54 -4
  53. package/locales/zh-CN/plugin.json +22 -1
  54. package/locales/zh-TW/chat.json +7 -0
  55. package/locales/zh-TW/models.json +43 -4
  56. package/locales/zh-TW/plugin.json +22 -1
  57. package/package.json +1 -1
  58. package/packages/builtin-tool-agent-builder/package.json +1 -0
  59. package/packages/builtin-tool-agent-builder/src/client/Inspector/GetAvailableModels/index.tsx +66 -0
  60. package/packages/builtin-tool-agent-builder/src/client/Inspector/InstallPlugin/index.tsx +63 -0
  61. package/packages/builtin-tool-agent-builder/src/client/Inspector/SearchMarketTools/index.tsx +64 -0
  62. package/packages/builtin-tool-agent-builder/src/client/Inspector/UpdateConfig/index.tsx +94 -0
  63. package/packages/builtin-tool-agent-builder/src/client/Inspector/UpdatePrompt/index.tsx +96 -0
  64. package/packages/builtin-tool-agent-builder/src/client/Inspector/index.ts +29 -0
  65. package/packages/builtin-tool-agent-builder/src/client/index.ts +13 -0
  66. package/packages/builtin-tool-agent-builder/src/executor.ts +132 -0
  67. package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/ExecuteCode/index.tsx +5 -14
  68. package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/RunCommand/index.tsx +5 -13
  69. package/packages/builtin-tool-group-agent-builder/package.json +7 -1
  70. package/packages/builtin-tool-group-agent-builder/src/ExecutionRuntime/index.ts +331 -87
  71. package/packages/builtin-tool-group-agent-builder/src/client/Inspector/BatchCreateAgents/index.tsx +110 -0
  72. package/packages/builtin-tool-group-agent-builder/src/client/Inspector/CreateAgent/index.tsx +72 -0
  73. package/packages/builtin-tool-group-agent-builder/src/client/Inspector/InviteAgent/index.tsx +57 -0
  74. package/packages/builtin-tool-group-agent-builder/src/client/Inspector/RemoveAgent/index.tsx +57 -0
  75. package/packages/builtin-tool-group-agent-builder/src/client/Inspector/SearchAgent/index.tsx +66 -0
  76. package/packages/builtin-tool-group-agent-builder/src/client/Inspector/UpdateAgentPrompt/index.tsx +120 -0
  77. package/packages/builtin-tool-group-agent-builder/src/client/Inspector/UpdateGroup/index.tsx +87 -0
  78. package/packages/builtin-tool-group-agent-builder/src/client/Inspector/UpdateGroupPrompt/index.tsx +99 -0
  79. package/packages/builtin-tool-group-agent-builder/src/client/Inspector/index.ts +52 -0
  80. package/packages/builtin-tool-group-agent-builder/src/client/Render/BatchCreateAgents.tsx +103 -0
  81. package/packages/builtin-tool-group-agent-builder/src/client/Render/UpdateAgentPrompt/index.tsx +36 -0
  82. package/packages/builtin-tool-group-agent-builder/src/client/Render/UpdateGroupPrompt/index.tsx +36 -0
  83. package/packages/builtin-tool-group-agent-builder/src/client/Render/index.ts +16 -0
  84. package/packages/builtin-tool-group-agent-builder/src/client/Streaming/BatchCreateAgents/index.tsx +88 -0
  85. package/packages/builtin-tool-group-agent-builder/src/client/Streaming/UpdateAgentPrompt/index.tsx +37 -0
  86. package/packages/builtin-tool-group-agent-builder/src/client/Streaming/UpdateGroupPrompt/index.tsx +35 -0
  87. package/packages/builtin-tool-group-agent-builder/src/client/Streaming/index.ts +22 -0
  88. package/packages/builtin-tool-group-agent-builder/src/client/index.ts +26 -0
  89. package/packages/builtin-tool-group-agent-builder/src/executor.ts +284 -0
  90. package/packages/builtin-tool-group-agent-builder/src/index.ts +1 -14
  91. package/packages/builtin-tool-group-agent-builder/src/manifest.ts +160 -15
  92. package/packages/builtin-tool-group-agent-builder/src/systemRole.ts +232 -46
  93. package/packages/builtin-tool-group-agent-builder/src/types.ts +191 -41
  94. package/packages/builtin-tool-group-management/src/client/Inspector/Broadcast/index.tsx +2 -2
  95. package/packages/builtin-tool-group-management/src/manifest.ts +1 -1
  96. package/packages/builtin-tool-gtd/src/client/Inspector/ClearTodos/index.tsx +5 -11
  97. package/packages/builtin-tool-gtd/src/client/Inspector/CompleteTodos/index.tsx +3 -9
  98. package/packages/builtin-tool-gtd/src/client/Inspector/CreatePlan/index.tsx +6 -15
  99. package/packages/builtin-tool-gtd/src/client/Inspector/CreateTodos/index.tsx +3 -9
  100. package/packages/builtin-tool-gtd/src/client/Inspector/ExecTask/index.tsx +6 -17
  101. package/packages/builtin-tool-gtd/src/client/Inspector/RemoveTodos/index.tsx +3 -9
  102. package/packages/builtin-tool-gtd/src/client/Inspector/UpdatePlan/index.tsx +3 -9
  103. package/packages/builtin-tool-gtd/src/client/Inspector/UpdateTodos/index.tsx +3 -9
  104. package/packages/builtin-tool-knowledge-base/src/client/Inspector/ReadKnowledge/index.tsx +4 -16
  105. package/packages/builtin-tool-knowledge-base/src/client/Inspector/SearchKnowledgeBase/index.tsx +5 -16
  106. package/packages/builtin-tool-local-system/src/client/Inspector/EditLocalFile/index.tsx +4 -12
  107. package/packages/builtin-tool-local-system/src/client/Inspector/GlobLocalFiles/index.tsx +5 -13
  108. package/packages/builtin-tool-local-system/src/client/Inspector/GrepContent/index.tsx +5 -16
  109. package/packages/builtin-tool-local-system/src/client/Inspector/ListLocalFiles/index.tsx +5 -16
  110. package/packages/builtin-tool-local-system/src/client/Inspector/ReadLocalFile/index.tsx +5 -16
  111. package/packages/builtin-tool-local-system/src/client/Inspector/RenameLocalFile/index.tsx +5 -11
  112. package/packages/builtin-tool-local-system/src/client/Inspector/RunCommand/index.tsx +5 -13
  113. package/packages/builtin-tool-local-system/src/client/Inspector/SearchLocalFiles/index.tsx +5 -16
  114. package/packages/builtin-tool-local-system/src/client/Inspector/WriteLocalFile/index.tsx +6 -15
  115. package/packages/builtin-tool-notebook/src/client/Inspector/CreateDocument/index.tsx +7 -15
  116. package/packages/builtin-tool-page-agent/src/client/Inspector/EditTitle/index.tsx +5 -14
  117. package/packages/builtin-tool-page-agent/src/client/Inspector/GetPageContent/index.tsx +7 -8
  118. package/packages/builtin-tool-page-agent/src/client/Inspector/InitPage/index.tsx +4 -10
  119. package/packages/builtin-tool-page-agent/src/client/Inspector/ModifyNodes/index.tsx +3 -9
  120. package/packages/builtin-tool-page-agent/src/client/Inspector/ReplaceText/index.tsx +5 -11
  121. package/packages/builtin-tool-web-browsing/src/client/Inspector/CrawlMultiPages/index.tsx +6 -15
  122. package/packages/builtin-tool-web-browsing/src/client/Inspector/CrawlSinglePage/index.tsx +6 -15
  123. package/packages/builtin-tool-web-browsing/src/client/Inspector/Search/index.tsx +4 -15
  124. package/packages/database/src/models/chatGroup.ts +1 -1
  125. package/packages/model-bank/src/aiModels/aihubmix.ts +2 -1
  126. package/packages/model-bank/src/aiModels/google.ts +2 -1
  127. package/packages/model-bank/src/aiModels/infiniai.ts +9 -6
  128. package/packages/model-bank/src/aiModels/minimax.ts +9 -5
  129. package/packages/model-bank/src/aiModels/ollamacloud.ts +4 -2
  130. package/packages/model-bank/src/aiModels/vertexai.ts +2 -1
  131. package/packages/types/src/agentGroup/index.ts +8 -0
  132. package/patches/@upstash__qstash.patch +13 -1
  133. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Header/Nav.tsx +1 -1
  134. package/src/app/[variants]/(main)/agent/cron/[cronId]/index.tsx +4 -3
  135. package/src/app/[variants]/(main)/agent/profile/features/ProfileEditor/index.tsx +1 -1
  136. package/src/app/[variants]/(main)/agent/profile/features/store/action.ts +18 -21
  137. package/src/app/[variants]/(main)/group/_layout/GroupIdSync.tsx +6 -1
  138. package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/AgentProfilePopup.tsx +29 -21
  139. package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/GroupMember.tsx +1 -0
  140. package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/GroupMemberItem.tsx +35 -18
  141. package/src/app/[variants]/(main)/group/_layout/Sidebar/Header/AddTopicButon.tsx +2 -10
  142. package/src/app/[variants]/(main)/group/_layout/Sidebar/Header/Nav.tsx +10 -2
  143. package/src/app/[variants]/(main)/group/_layout/Sidebar/Header/index.tsx +1 -2
  144. package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/AgentBuilderProvider.tsx +1 -0
  145. package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/TopicSelector.tsx +15 -9
  146. package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/index.tsx +12 -6
  147. package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor/AgentHeader.tsx → GroupProfile/GroupHeader.tsx} +22 -29
  148. package/src/app/[variants]/(main)/group/profile/features/GroupProfile/index.tsx +96 -0
  149. package/src/app/[variants]/(main)/group/profile/features/Header/AgentBuilderToggle.tsx +3 -4
  150. package/src/app/[variants]/(main)/group/profile/features/Header/AutoSaveHint.tsx +11 -7
  151. package/src/app/[variants]/(main)/group/profile/features/Header/ChromeTabs/index.tsx +147 -0
  152. package/src/app/[variants]/(main)/group/profile/features/Header/index.tsx +104 -13
  153. package/src/app/[variants]/(main)/group/profile/features/MemberProfile/AgentHeader.tsx +222 -0
  154. package/src/app/[variants]/(main)/group/profile/features/MemberProfile/index.tsx +155 -0
  155. package/src/app/[variants]/(main)/group/profile/features/ProfileHydration.tsx +63 -5
  156. package/src/app/[variants]/(main)/group/profile/index.tsx +34 -37
  157. package/src/app/[variants]/(mobile)/(home)/_layout/SessionHydration.tsx +1 -1
  158. package/src/app/[variants]/(mobile)/(home)/features/SessionListContent/List/Item/index.tsx +1 -1
  159. package/src/features/AgentBuilder/index.tsx +16 -1
  160. package/src/features/Conversation/Messages/AssistantGroup/Tool/Inspector/StatusIndicator.tsx +3 -2
  161. package/src/features/EditorCanvas/EditorCanvas.test.tsx +206 -0
  162. package/src/features/EditorCanvas/EditorDataMode.tsx +53 -19
  163. package/src/features/EditorModal/index.tsx +2 -2
  164. package/src/features/NavPanel/components/SessionHydration.tsx +1 -1
  165. package/src/features/ShareModal/ShareImage/ChatList/index.tsx +1 -1
  166. package/src/features/ShareModal/SharePdf/index.tsx +1 -1
  167. package/src/hooks/useBidirectionalQuerySync.ts +112 -0
  168. package/src/locales/default/chat.ts +10 -0
  169. package/src/locales/default/plugin.ts +22 -1
  170. package/src/server/modules/AgentRuntime/RuntimeExecutors.ts +45 -45
  171. package/src/server/modules/KeyVaultsEncrypt/index.ts +6 -6
  172. package/src/server/modules/S3/index.ts +1 -1
  173. package/src/server/routers/lambda/agent.ts +24 -0
  174. package/src/server/routers/lambda/agentGroup.ts +39 -0
  175. package/src/services/agent.ts +22 -0
  176. package/src/services/chatGroup/index.ts +14 -0
  177. package/src/store/agent/selectors/selectors.ts +3 -0
  178. package/src/store/agentGroup/initialState.ts +6 -0
  179. package/src/store/agentGroup/selectors/byId.ts +3 -1
  180. package/src/store/agentGroup/selectors/current.ts +2 -2
  181. package/src/store/agentGroup/slices/lifecycle.ts +18 -0
  182. package/src/store/chat/agents/__tests__/createAgentExecutors/fixtures/mockStore.ts +1 -1
  183. package/src/store/chat/slices/aiAgent/actions/__tests__/agentGroup.test.ts +4 -1
  184. package/src/store/chat/slices/aiAgent/actions/agentGroup.ts +1 -1
  185. package/src/store/chat/slices/aiChat/actions/__tests__/conversationLifecycle.test.ts +65 -0
  186. package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +2 -1
  187. package/src/store/chat/slices/builtinTool/actions/__tests__/search.test.ts +1 -1
  188. package/src/store/chat/slices/builtinTool/actions/index.ts +1 -6
  189. package/src/store/chat/slices/message/action.test.ts +5 -5
  190. package/src/store/chat/slices/message/actions/publicApi.ts +5 -5
  191. package/src/store/chat/slices/message/initialState.ts +0 -5
  192. package/src/store/chat/slices/message/selectors/displayMessage.test.ts +4 -4
  193. package/src/store/chat/slices/plugin/action.test.ts +54 -19
  194. package/src/store/chat/slices/plugin/actions/pluginTypes.ts +15 -21
  195. package/src/store/chat/slices/topic/action.test.ts +74 -24
  196. package/src/store/chat/slices/topic/action.ts +21 -13
  197. package/src/store/chat/slices/topic/selectors.test.ts +1 -1
  198. package/src/store/global/initialState.ts +10 -0
  199. package/src/store/global/selectors/systemStatus.ts +5 -0
  200. package/src/store/groupProfile/action.ts +168 -0
  201. package/src/store/groupProfile/index.ts +16 -0
  202. package/src/{app/[variants]/(main)/group/profile/features/store → store/groupProfile}/initialState.ts +17 -0
  203. package/src/store/groupProfile/selectors.ts +13 -0
  204. package/src/store/tool/slices/builtin/executors/index.ts +4 -0
  205. package/src/styles/text.ts +16 -0
  206. package/src/tools/inspectors.ts +13 -0
  207. package/src/tools/renders.ts +3 -0
  208. package/src/tools/streamings.ts +8 -0
  209. package/src/app/[variants]/(main)/group/profile/features/EditorCanvas/TypoBar.tsx +0 -129
  210. package/src/app/[variants]/(main)/group/profile/features/EditorCanvas/index.tsx +0 -138
  211. package/src/app/[variants]/(main)/group/profile/features/EditorCanvas/useSlashItems.tsx +0 -139
  212. package/src/app/[variants]/(main)/group/profile/features/ProfileEditor/index.tsx +0 -82
  213. package/src/app/[variants]/(main)/group/profile/features/ProfileProvider.tsx +0 -20
  214. package/src/app/[variants]/(main)/group/profile/features/StoreUpdater.tsx +0 -24
  215. package/src/app/[variants]/(main)/group/profile/features/store/action.ts +0 -163
  216. package/src/app/[variants]/(main)/group/profile/features/store/index.ts +0 -23
  217. package/src/app/[variants]/(main)/group/profile/features/store/selectors.ts +0 -7
  218. package/src/features/EditorModal/EditorCanvas.tsx +0 -84
  219. package/src/features/EditorModal/Typobar.tsx +0 -139
  220. package/src/store/chat/slices/builtinTool/actions/agentBuilder.ts +0 -192
  221. package/src/store/chat/slices/builtinTool/actions/groupAgentBuilder.ts +0 -242
  222. package/src/tools/executionRuntimes.ts +0 -14
  223. /package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor → MemberProfile}/AgentTool.tsx +0 -0
  224. /package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor → MemberProfile}/MentionList/MentionDropdown.tsx +0 -0
  225. /package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor → MemberProfile}/MentionList/index.tsx +0 -0
  226. /package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor → MemberProfile}/MentionList/types.ts +0 -0
  227. /package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor → MemberProfile}/MentionList/useMentionItems.tsx +0 -0
@@ -0,0 +1,147 @@
1
+ 'use client';
2
+
3
+ import { Avatar, Flexbox } from '@lobehub/ui';
4
+ import { createStaticStyles, cx } from 'antd-style';
5
+ import { Plus } from 'lucide-react';
6
+ import { ReactNode, memo } from 'react';
7
+ import { useTranslation } from 'react-i18next';
8
+
9
+ const styles = createStaticStyles(({ css, cssVar: cv }) => ({
10
+ addButton: css`
11
+ cursor: pointer;
12
+
13
+ display: flex;
14
+ flex-shrink: 0;
15
+ align-items: center;
16
+ justify-content: center;
17
+
18
+ width: 28px;
19
+ height: 28px;
20
+ border-radius: 6px;
21
+
22
+ color: ${cv.colorTextTertiary};
23
+
24
+ background: transparent;
25
+
26
+ transition: all 0.2s;
27
+
28
+ &:hover {
29
+ color: ${cv.colorTextSecondary};
30
+ background: ${cv.colorFillTertiary};
31
+ }
32
+ `,
33
+ container: css`
34
+ display: flex;
35
+ gap: 2px;
36
+ align-items: center;
37
+ `,
38
+ externalTag: css`
39
+ flex-shrink: 0;
40
+
41
+ padding-block: 1px;
42
+ padding-inline: 4px;
43
+ border-radius: 4px;
44
+
45
+ font-size: 10px;
46
+ line-height: 1.2;
47
+
48
+ background: ${cv.colorFillSecondary};
49
+ `,
50
+ tab: css`
51
+ cursor: pointer;
52
+
53
+ display: flex;
54
+ flex-shrink: 0;
55
+ gap: 6px;
56
+ align-items: center;
57
+
58
+ height: 32px;
59
+ padding-block: 6px;
60
+ padding-inline: 12px;
61
+ border-radius: 8px;
62
+
63
+ color: ${cv.colorTextTertiary};
64
+
65
+ background: transparent;
66
+
67
+ transition: all 0.2s;
68
+
69
+ &:hover {
70
+ color: ${cv.colorTextSecondary};
71
+ background: ${cv.colorFillTertiary};
72
+ }
73
+ `,
74
+ tabActive: css`
75
+ color: ${cv.colorText};
76
+ background: ${cv.colorFillTertiary};
77
+
78
+ &:hover {
79
+ color: ${cv.colorText};
80
+ background: ${cv.colorFillTertiary};
81
+ }
82
+ `,
83
+ tabTitle: css`
84
+ overflow: hidden;
85
+
86
+ max-width: 120px;
87
+
88
+ font-size: 13px;
89
+ line-height: 1.2;
90
+ text-overflow: ellipsis;
91
+ white-space: nowrap;
92
+ `,
93
+ }));
94
+
95
+ export interface ChromeTabItem {
96
+ avatar?: string;
97
+ icon?: ReactNode;
98
+ id: string;
99
+ isExternal?: boolean;
100
+ title: string;
101
+ }
102
+
103
+ interface ChromeTabsProps {
104
+ activeId: string;
105
+ items: ChromeTabItem[];
106
+ onAdd?: () => void;
107
+ onChange: (id: string) => void;
108
+ }
109
+
110
+ const ChromeTabs = memo<ChromeTabsProps>(({ items, activeId, onChange, onAdd }) => {
111
+ const { t } = useTranslation('chat');
112
+
113
+ return (
114
+ <div className={styles.container}>
115
+ {items.map((item) => {
116
+ const isActive = item.id === activeId;
117
+
118
+ return (
119
+ <div
120
+ className={cx(styles.tab, isActive && styles.tabActive)}
121
+ key={item.id}
122
+ onClick={() => onChange(item.id)}
123
+ >
124
+ <Flexbox align="center" gap={6} horizontal>
125
+ {item.icon ? (
126
+ item.icon
127
+ ) : item.avatar ? (
128
+ <Avatar avatar={item.avatar} size={18} />
129
+ ) : null}
130
+ <span className={styles.tabTitle}>{item.title}</span>
131
+ {item.isExternal && (
132
+ <span className={styles.externalTag}>{t('group.profile.external')}</span>
133
+ )}
134
+ </Flexbox>
135
+ </div>
136
+ );
137
+ })}
138
+ {onAdd && (
139
+ <div className={styles.addButton} onClick={onAdd}>
140
+ <Plus size={16} />
141
+ </div>
142
+ )}
143
+ </div>
144
+ );
145
+ });
146
+
147
+ export default ChromeTabs;
@@ -1,23 +1,114 @@
1
- import { memo } from 'react';
1
+ 'use client';
2
2
 
3
- import NavHeader from '@/features/NavHeader';
4
- import WideScreenButton from '@/features/WideScreenContainer/WideScreenButton';
3
+ import { Flexbox } from '@lobehub/ui';
4
+ import { createStyles } from 'antd-style';
5
+ import { Crown, Users } from 'lucide-react';
6
+ import { memo, useMemo, useState } from 'react';
7
+ import { useTranslation } from 'react-i18next';
8
+
9
+ import AddGroupMemberModal from '@/app/[variants]/(main)/group/_layout/Sidebar/AddGroupMemberModal';
10
+ import { parseAsString, useQueryState } from '@/hooks/useQueryParam';
11
+ import { useAgentGroupStore } from '@/store/agentGroup';
12
+ import { agentGroupSelectors } from '@/store/agentGroup/selectors';
5
13
 
6
14
  import AgentBuilderToggle from './AgentBuilderToggle';
7
- import AutoSaveHint from './AutoSaveHint';
15
+ import ChromeTabs, { type ChromeTabItem } from './ChromeTabs';
16
+
17
+ const useStyles = createStyles(({ css, token }) => ({
18
+ header: css`
19
+ overflow: hidden;
20
+ flex: none;
21
+
22
+ width: 100%;
23
+ height: 44px;
24
+ padding-block: 8px;
25
+ padding-inline: 12px;
26
+ border-block-end: 1px solid ${token.colorBorderSecondary};
27
+ `,
28
+ tabsWrapper: css`
29
+ scrollbar-width: none;
30
+ overflow-x: auto;
31
+ flex: 1;
32
+ min-width: 0;
33
+
34
+ &::-webkit-scrollbar {
35
+ display: none;
36
+ }
37
+ `,
38
+ }));
8
39
 
9
40
  const Header = memo(() => {
41
+ const { t } = useTranslation('chat');
42
+ const { styles } = useStyles();
43
+
44
+ const [showAddModal, setShowAddModal] = useState(false);
45
+
46
+ const members = useAgentGroupStore(agentGroupSelectors.currentGroupAgents);
47
+ const activeGroupId = useAgentGroupStore(agentGroupSelectors.activeGroupId);
48
+ const addAgentsToGroup = useAgentGroupStore((s) => s.addAgentsToGroup);
49
+
50
+ // Use URL query param for selected tab
51
+ const [selectedTabId, setSelectedTabId] = useQueryState(
52
+ 'tab',
53
+ parseAsString.withDefault('group'),
54
+ );
55
+
56
+ const existingMemberIds = useMemo(() => members.map((a) => a.id), [members]);
57
+
58
+ const tabItems = useMemo<ChromeTabItem[]>(() => {
59
+ const items: ChromeTabItem[] = [
60
+ {
61
+ icon: <Users size={16} />,
62
+ id: 'group',
63
+ title: t('group.profile.groupSettings'),
64
+ },
65
+ ];
66
+
67
+ // Add agent tabs
68
+ for (const agent of members) {
69
+ items.push({
70
+ avatar: agent.isSupervisor ? undefined : agent.avatar || undefined,
71
+ icon: agent.isSupervisor ? <Crown size={16} /> : undefined,
72
+ id: agent.id,
73
+ isExternal: !agent.isSupervisor && !agent.virtual,
74
+ title: agent.isSupervisor ? t('group.profile.supervisor') : agent.title || 'Untitled Agent',
75
+ });
76
+ }
77
+
78
+ return items;
79
+ }, [members, t]);
80
+
81
+ const handleAddMembers = async (agentIds: string[]) => {
82
+ if (!activeGroupId) return;
83
+ await addAgentsToGroup(activeGroupId, agentIds);
84
+ setShowAddModal(false);
85
+ };
86
+
10
87
  return (
11
- <NavHeader
12
- left={<AutoSaveHint />}
13
- right={
14
- <>
15
- <WideScreenButton />
88
+ <>
89
+ <Flexbox align="center" className={styles.header} horizontal justify="space-between">
90
+ <div className={styles.tabsWrapper}>
91
+ <ChromeTabs
92
+ activeId={selectedTabId}
93
+ items={tabItems}
94
+ onAdd={() => setShowAddModal(true)}
95
+ onChange={setSelectedTabId}
96
+ />
97
+ </div>
98
+ <Flexbox align="center" flex="none" gap={8} horizontal style={{ marginInlineStart: 12 }}>
16
99
  <AgentBuilderToggle />
17
- {/* TODO: Add GroupPublishButton when group publishing is supported */}
18
- </>
19
- }
20
- />
100
+ </Flexbox>
101
+ </Flexbox>
102
+ {activeGroupId && (
103
+ <AddGroupMemberModal
104
+ existingMembers={existingMemberIds}
105
+ groupId={activeGroupId}
106
+ onCancel={() => setShowAddModal(false)}
107
+ onConfirm={handleAddMembers}
108
+ open={showAddModal}
109
+ />
110
+ )}
111
+ </>
21
112
  );
22
113
  });
23
114
 
@@ -0,0 +1,222 @@
1
+ 'use client';
2
+
3
+ import { DEFAULT_AVATAR, EDITOR_DEBOUNCE_TIME } from '@lobechat/const';
4
+ import { Block, Flexbox, Icon, Input, Skeleton, Tooltip } from '@lobehub/ui';
5
+ import { useDebounceFn } from 'ahooks';
6
+ import { message } from 'antd';
7
+ import isEqual from 'fast-deep-equal';
8
+ import { PaletteIcon } from 'lucide-react';
9
+ import { Suspense, memo, useCallback, useEffect, useState } from 'react';
10
+ import { useTranslation } from 'react-i18next';
11
+
12
+ import SupervisorAvatar from '@/app/[variants]/(main)/group/features/GroupAvatar';
13
+ import EmojiPicker from '@/components/EmojiPicker';
14
+ import BackgroundSwatches from '@/features/AgentSetting/AgentMeta/BackgroundSwatches';
15
+ import { useAgentStore } from '@/store/agent';
16
+ import { agentSelectors } from '@/store/agent/selectors';
17
+ import { useFileStore } from '@/store/file';
18
+ import { useGlobalStore } from '@/store/global';
19
+ import { globalGeneralSelectors } from '@/store/global/selectors';
20
+ import { useGroupProfileStore } from '@/store/groupProfile';
21
+
22
+ const MAX_AVATAR_SIZE = 1024 * 1024; // 1MB limit for server actions
23
+
24
+ interface AgentHeaderProps {
25
+ /**
26
+ * When true, shows fixed title (supervisor) and disables avatar editing
27
+ */
28
+ readOnly?: boolean;
29
+ }
30
+
31
+ const AgentHeader = memo<AgentHeaderProps>(({ readOnly }) => {
32
+ const { t } = useTranslation(['setting', 'common', 'chat']);
33
+ const locale = useGlobalStore(globalGeneralSelectors.currentLanguage);
34
+
35
+ // Get agentId from profile store
36
+ const agentId = useGroupProfileStore((s) => s.activeTabId);
37
+
38
+ // Get agent meta by agentId
39
+ const agentMeta = useAgentStore(agentSelectors.getAgentMetaById(agentId), isEqual);
40
+ const optimisticUpdateAgentMeta = useAgentStore((s) => s.optimisticUpdateAgentMeta);
41
+
42
+ // File upload
43
+ const uploadWithProgress = useFileStore((s) => s.uploadWithProgress);
44
+ const [uploading, setUploading] = useState(false);
45
+
46
+ // Local state for inputs (to avoid stuttering during typing)
47
+ const [localTitle, setLocalTitle] = useState(agentMeta.title || '');
48
+
49
+ // Sync local state when meta changes from external source
50
+ useEffect(() => {
51
+ setLocalTitle(agentMeta.title || '');
52
+ }, [agentMeta.title]);
53
+
54
+ // Debounced save for title - save to agent store
55
+ const { run: debouncedSaveTitle } = useDebounceFn(
56
+ (value: string) => {
57
+ optimisticUpdateAgentMeta(agentId, { title: value });
58
+ },
59
+ { wait: EDITOR_DEBOUNCE_TIME },
60
+ );
61
+
62
+ // Handle avatar change (immediate save) - save to agent store (supervisor agent)
63
+ const handleAvatarChange = (emoji: string) => {
64
+ optimisticUpdateAgentMeta(agentId, { avatar: emoji });
65
+ };
66
+
67
+ // Handle avatar upload
68
+ const handleAvatarUpload = useCallback(
69
+ async (file: File) => {
70
+ if (file.size > MAX_AVATAR_SIZE) {
71
+ message.error(t('settingAgent.avatar.sizeExceeded', { ns: 'setting' }));
72
+ return;
73
+ }
74
+
75
+ setUploading(true);
76
+ try {
77
+ const result = await uploadWithProgress({ file });
78
+ console.log('result', result);
79
+ if (result?.url) {
80
+ optimisticUpdateAgentMeta(agentId, { avatar: result.url });
81
+ }
82
+ } finally {
83
+ setUploading(false);
84
+ }
85
+ },
86
+ [uploadWithProgress, optimisticUpdateAgentMeta, agentId, t],
87
+ );
88
+
89
+ // Handle avatar delete
90
+ const handleAvatarDelete = useCallback(() => {
91
+ optimisticUpdateAgentMeta(agentId, { avatar: undefined });
92
+ }, [optimisticUpdateAgentMeta, agentId]);
93
+
94
+ // Handle background color change (immediate save) - save to agent store (supervisor agent)
95
+ const handleBackgroundColorChange = (color?: string) => {
96
+ if (color !== undefined) {
97
+ optimisticUpdateAgentMeta(agentId, { backgroundColor: color });
98
+ }
99
+ };
100
+
101
+ // ReadOnly mode: show fixed avatar and title (for supervisor)
102
+ if (readOnly) {
103
+ return (
104
+ <Flexbox
105
+ gap={16}
106
+ onClick={(e) => {
107
+ e.stopPropagation();
108
+ e.preventDefault();
109
+ }}
110
+ paddingBlock={16}
111
+ style={{
112
+ cursor: 'default',
113
+ }}
114
+ >
115
+ <Block height={72} width={72}>
116
+ <SupervisorAvatar size={72} />
117
+ </Block>
118
+ <Flexbox
119
+ style={{
120
+ fontSize: 36,
121
+ fontWeight: 600,
122
+ }}
123
+ >
124
+ {t('group.profile.supervisor', { ns: 'chat' })}
125
+ </Flexbox>
126
+ </Flexbox>
127
+ );
128
+ }
129
+
130
+ return (
131
+ <Flexbox
132
+ gap={16}
133
+ onClick={(e) => {
134
+ e.stopPropagation();
135
+ e.preventDefault();
136
+ }}
137
+ paddingBlock={16}
138
+ style={{
139
+ cursor: 'default',
140
+ }}
141
+ >
142
+ <EmojiPicker
143
+ allowDelete={!!agentMeta.avatar}
144
+ allowUpload
145
+ background={
146
+ agentMeta.backgroundColor && agentMeta.backgroundColor !== 'rgba(0,0,0,0)'
147
+ ? agentMeta.backgroundColor
148
+ : undefined
149
+ }
150
+ customRender={
151
+ agentMeta.avatar && agentMeta.avatar !== DEFAULT_AVATAR
152
+ ? undefined
153
+ : () => {
154
+ return (
155
+ <Block clickable height={72} width={72}>
156
+ <SupervisorAvatar size={72} />
157
+ </Block>
158
+ );
159
+ }
160
+ }
161
+ customTabs={[
162
+ {
163
+ label: (
164
+ <Tooltip title={t('settingAgent.backgroundColor.title', { ns: 'setting' })}>
165
+ <Icon icon={PaletteIcon} size={{ size: 20, strokeWidth: 2.5 }} />
166
+ </Tooltip>
167
+ ),
168
+ render: () => (
169
+ <Flexbox padding={8} width={332}>
170
+ <Suspense
171
+ fallback={
172
+ <Flexbox gap={8}>
173
+ <Skeleton.Button block style={{ height: 38 }} />
174
+ <Skeleton.Button block style={{ height: 38 }} />
175
+ </Flexbox>
176
+ }
177
+ >
178
+ <BackgroundSwatches
179
+ gap={8}
180
+ onChange={handleBackgroundColorChange}
181
+ shape={'square'}
182
+ size={38}
183
+ value={agentMeta.backgroundColor}
184
+ />
185
+ </Suspense>
186
+ </Flexbox>
187
+ ),
188
+ value: 'background',
189
+ },
190
+ ]}
191
+ loading={uploading}
192
+ locale={locale}
193
+ onChange={handleAvatarChange}
194
+ onDelete={handleAvatarDelete}
195
+ onUpload={handleAvatarUpload}
196
+ popupProps={{
197
+ placement: 'bottomLeft',
198
+ }}
199
+ shape={'square'}
200
+ size={72}
201
+ value={agentMeta.avatar}
202
+ />
203
+ <Input
204
+ onChange={(e) => {
205
+ setLocalTitle(e.target.value);
206
+ debouncedSaveTitle(e.target.value);
207
+ }}
208
+ placeholder={t('settingAgent.name.placeholder', { ns: 'setting' })}
209
+ style={{
210
+ fontSize: 36,
211
+ fontWeight: 600,
212
+ padding: 0,
213
+ width: '100%',
214
+ }}
215
+ value={localTitle}
216
+ variant={'borderless'}
217
+ />
218
+ </Flexbox>
219
+ );
220
+ });
221
+
222
+ export default AgentHeader;
@@ -0,0 +1,155 @@
1
+ 'use client';
2
+
3
+ import { Alert, Button, Flexbox, Icon } from '@lobehub/ui';
4
+ import { Divider } from 'antd';
5
+ import isEqual from 'fast-deep-equal';
6
+ import { InfoIcon, PlayIcon } from 'lucide-react';
7
+ import React, { memo, useCallback, useMemo } from 'react';
8
+ import { useTranslation } from 'react-i18next';
9
+ import urlJoin from 'url-join';
10
+
11
+ import { EditorCanvas } from '@/features/EditorCanvas';
12
+ import ModelSelect from '@/features/ModelSelect';
13
+ import { useQueryRoute } from '@/hooks/useQueryRoute';
14
+ import { useAgentStore } from '@/store/agent';
15
+ import { agentByIdSelectors } from '@/store/agent/selectors';
16
+ import { useAgentGroupStore } from '@/store/agentGroup';
17
+ import { agentGroupSelectors } from '@/store/agentGroup/selectors';
18
+ import { useGroupProfileStore } from '@/store/groupProfile';
19
+
20
+ import AutoSaveHint from '../Header/AutoSaveHint';
21
+ import AgentHeader from './AgentHeader';
22
+ import AgentTool from './AgentTool';
23
+
24
+ const MemberProfile = memo(() => {
25
+ const { t } = useTranslation(['setting', 'chat']);
26
+
27
+ // Get agentId from profile store (activeTabId is the selected agent ID)
28
+ const agentId = useGroupProfileStore((s) => s.activeTabId);
29
+ const editor = useGroupProfileStore((s) => s.editor);
30
+ const handleContentChange = useGroupProfileStore((s) => s.handleContentChange);
31
+
32
+ // Get agent config by agentId
33
+ const config = useAgentStore(agentByIdSelectors.getAgentConfigById(agentId), isEqual);
34
+ const updateAgentConfigById = useAgentStore((s) => s.updateAgentConfigById);
35
+
36
+ const groupId = useAgentGroupStore(agentGroupSelectors.activeGroupId);
37
+ const currentGroup = useAgentGroupStore(agentGroupSelectors.currentGroup);
38
+ const currentGroupAgents = useAgentGroupStore(agentGroupSelectors.currentGroupAgents);
39
+ const router = useQueryRoute();
40
+
41
+ // Check if the current agent is the supervisor
42
+ const isSupervisor = currentGroup?.supervisorAgentId === agentId;
43
+
44
+ // Compute isExternal based on group member properties
45
+ const isExternal = useMemo(() => {
46
+ const agent = currentGroupAgents.find((a) => a.id === agentId);
47
+ return agent ? !agent.isSupervisor && !agent.virtual : false;
48
+ }, [currentGroupAgents, agentId]);
49
+
50
+ // Wrap updateAgentConfigById for saving editor content
51
+ const updateContent = useCallback(
52
+ async (payload: { content: string; editorData: Record<string, any> }) => {
53
+ await updateAgentConfigById(agentId, {
54
+ editorData: payload.editorData,
55
+ systemRole: payload.content,
56
+ });
57
+ },
58
+ [updateAgentConfigById, agentId],
59
+ );
60
+
61
+ // Handle editor content change
62
+ const onContentChange = useCallback(() => {
63
+ handleContentChange(updateContent);
64
+ }, [handleContentChange, updateContent]);
65
+
66
+ // Wrap updateAgentConfigById for ModelSelect
67
+ const updateAgentConfig = useCallback(
68
+ async (config: { model?: string; provider?: string }) => {
69
+ await updateAgentConfigById(agentId, config);
70
+ },
71
+ [updateAgentConfigById, agentId],
72
+ );
73
+
74
+ return (
75
+ <>
76
+ {/* External agent warning or AutoSaveHint */}
77
+ <Flexbox height={66} width={'100%'}>
78
+ {isExternal && !isSupervisor && (
79
+ <Alert
80
+ icon={<Icon icon={InfoIcon} />}
81
+ style={{ width: '100%' }}
82
+ title={t('group.profile.externalAgentWarning', { ns: 'chat' })}
83
+ type="secondary"
84
+ variant={'outlined'}
85
+ />
86
+ )}
87
+ <Flexbox paddingBlock={12}>
88
+ <AutoSaveHint />
89
+ </Flexbox>
90
+ </Flexbox>
91
+ <Flexbox
92
+ onClick={(e) => {
93
+ e.stopPropagation();
94
+ }}
95
+ style={{ cursor: 'default', marginBottom: 12 }}
96
+ >
97
+ {/* Header: Avatar + Name */}
98
+ <AgentHeader readOnly={isSupervisor} />
99
+ {/* Config Bar: Model Selector */}
100
+ <Flexbox
101
+ align={'center'}
102
+ gap={8}
103
+ horizontal
104
+ justify={'flex-start'}
105
+ style={{ marginBottom: 12 }}
106
+ >
107
+ <ModelSelect
108
+ onChange={updateAgentConfig}
109
+ value={{
110
+ model: config?.model,
111
+ provider: config?.provider,
112
+ }}
113
+ />
114
+ </Flexbox>
115
+ <AgentTool />
116
+ <Flexbox
117
+ align={'center'}
118
+ gap={8}
119
+ horizontal
120
+ justify={'flex-start'}
121
+ style={{ marginTop: 16 }}
122
+ >
123
+ <Button
124
+ icon={PlayIcon}
125
+ onClick={() => {
126
+ if (!groupId) return;
127
+ router.push(urlJoin('/group', groupId));
128
+ }}
129
+ type={'primary'}
130
+ >
131
+ {t('startConversation')}
132
+ </Button>
133
+ </Flexbox>
134
+ </Flexbox>
135
+ <Divider />
136
+ {/* Main Content: Prompt Editor */}
137
+ <EditorCanvas
138
+ editor={editor}
139
+ editorData={{
140
+ content: config?.systemRole,
141
+ editorData: config?.editorData,
142
+ }}
143
+ key={agentId}
144
+ onContentChange={onContentChange}
145
+ placeholder={
146
+ isSupervisor
147
+ ? t('group.profile.supervisorPlaceholder', { ns: 'chat' })
148
+ : t('settingAgent.prompt.placeholder')
149
+ }
150
+ />
151
+ </>
152
+ );
153
+ });
154
+
155
+ export default MemberProfile;