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

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 (48) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/changelog/v1.json +9 -0
  3. package/package.json +2 -2
  4. package/packages/types/package.json +1 -1
  5. package/packages/types/src/discover/assistants.ts +4 -0
  6. package/packages/types/src/discover/groupAgents.ts +196 -0
  7. package/packages/types/src/discover/index.ts +5 -1
  8. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/DetailProvider.tsx +19 -0
  9. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Members/index.tsx +137 -0
  10. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Nav.tsx +88 -0
  11. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Overview/index.tsx +213 -0
  12. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Related/index.tsx +85 -0
  13. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/SystemRole/TagList.tsx +20 -0
  14. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/SystemRole/index.tsx +71 -0
  15. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Versions/index.tsx +119 -0
  16. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/index.tsx +51 -0
  17. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Header.tsx +253 -0
  18. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/ActionButton/AddGroupAgent.tsx +222 -0
  19. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/ActionButton/index.tsx +34 -0
  20. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/Summary/index.tsx +42 -0
  21. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/index.tsx +41 -0
  22. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/StatusPage/index.tsx +104 -0
  23. package/src/app/[variants]/(main)/community/(detail)/group_agent/index.tsx +103 -0
  24. package/src/app/[variants]/(main)/community/(detail)/group_agent/loading.tsx +1 -0
  25. package/src/app/[variants]/(main)/community/(detail)/user/features/DetailProvider.tsx +7 -1
  26. package/src/app/[variants]/(main)/community/(detail)/user/features/UserContent.tsx +2 -0
  27. package/src/app/[variants]/(main)/community/(detail)/user/features/UserGroupCard.tsx +186 -0
  28. package/src/app/[variants]/(main)/community/(detail)/user/features/UserGroupList.tsx +59 -0
  29. package/src/app/[variants]/(main)/community/(detail)/user/index.tsx +3 -1
  30. package/src/app/[variants]/(main)/community/(list)/assistant/features/List/Item.tsx +26 -8
  31. package/src/app/[variants]/(main)/community/(list)/assistant/index.tsx +1 -0
  32. package/src/app/[variants]/(main)/group/profile/features/GroupProfile/index.tsx +2 -0
  33. package/src/app/[variants]/(main)/group/profile/features/Header/AgentPublishButton/PublishResultModal.tsx +2 -1
  34. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/GroupForkConfirmModal.tsx +60 -0
  35. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/GroupPublishResultModal.tsx +62 -0
  36. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/PublishButton.tsx +122 -0
  37. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/index.tsx +46 -0
  38. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/types.ts +12 -0
  39. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/useMarketGroupPublish.ts +211 -0
  40. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/utils.ts +22 -0
  41. package/src/app/[variants]/router/desktopRouter.config.tsx +7 -0
  42. package/src/locales/default/setting.ts +12 -0
  43. package/src/server/routers/lambda/market/agentGroup.ts +296 -0
  44. package/src/server/routers/lambda/market/index.ts +134 -4
  45. package/src/server/services/discover/index.ts +123 -7
  46. package/src/services/discover.ts +55 -0
  47. package/src/store/discover/slices/groupAgent/action.ts +80 -0
  48. package/src/store/discover/store.ts +3 -0
@@ -0,0 +1,122 @@
1
+ import { Button } from '@lobehub/ui';
2
+ import { ShapesUploadIcon } from '@lobehub/ui/icons';
3
+ import { memo, useCallback, useMemo, useState } from 'react';
4
+ import { useTranslation } from 'react-i18next';
5
+
6
+ import { message } from '@/components/AntdStaticMethods';
7
+ import { useMarketAuth } from '@/layout/AuthProvider/MarketAuth';
8
+ import { resolveMarketAuthError } from '@/layout/AuthProvider/MarketAuth/errors';
9
+
10
+ import GroupForkConfirmModal from './GroupForkConfirmModal';
11
+ import type { MarketPublishAction, OriginalGroupInfo } from './types';
12
+ import { useMarketGroupPublish } from './useMarketGroupPublish';
13
+
14
+ interface GroupPublishButtonProps {
15
+ action: MarketPublishAction;
16
+ onPublishSuccess?: (identifier: string) => void;
17
+ }
18
+
19
+ const PublishButton = memo<GroupPublishButtonProps>(({ action, onPublishSuccess }) => {
20
+ const { t } = useTranslation(['setting', 'marketAuth']);
21
+
22
+ const { isAuthenticated, isLoading, signIn } = useMarketAuth();
23
+ const { checkOwnership, isCheckingOwnership, isPublishing, publish } = useMarketGroupPublish({
24
+ action,
25
+ onSuccess: onPublishSuccess,
26
+ });
27
+
28
+ // Fork confirmation modal state
29
+ const [showForkModal, setShowForkModal] = useState(false);
30
+ const [originalGroupInfo, setOriginalGroupInfo] = useState<OriginalGroupInfo | null>(null);
31
+
32
+ const buttonConfig = useMemo(() => {
33
+ if (action === 'upload') {
34
+ return {
35
+ authenticated: t('marketPublish.uploadGroup.tooltip'),
36
+ unauthenticated: t('marketPublish.uploadGroup.tooltip'),
37
+ } as const;
38
+ }
39
+
40
+ const submitText = t('submitGroupModal.tooltips');
41
+
42
+ return {
43
+ authenticated: submitText,
44
+ unauthenticated: t('marketPublish.submitGroup.tooltip'),
45
+ } as const;
46
+ }, [action, t]);
47
+
48
+ const doPublish = useCallback(async () => {
49
+ // Check ownership before publishing
50
+ const { needsForkConfirm, originalGroup } = await checkOwnership();
51
+
52
+ if (needsForkConfirm && originalGroup) {
53
+ // Show fork confirmation modal
54
+ setOriginalGroupInfo(originalGroup);
55
+ setShowForkModal(true);
56
+ return;
57
+ }
58
+
59
+ // No confirmation needed, proceed with publish
60
+ await publish();
61
+ }, [checkOwnership, publish]);
62
+
63
+ const handleButtonClick = useCallback(async () => {
64
+ if (!isAuthenticated) {
65
+ try {
66
+ await signIn();
67
+ // After authentication, proceed with ownership check and publish
68
+ await doPublish();
69
+ } catch (error) {
70
+ console.error(`[GroupPublishButton][${action}] Authorization failed:`, error);
71
+ const normalizedError = resolveMarketAuthError(error);
72
+ message.error({
73
+ content: t(`errors.${normalizedError.code}`, { ns: 'marketAuth' }),
74
+ key: 'market-auth',
75
+ });
76
+ }
77
+ return;
78
+ }
79
+
80
+ // User is authenticated, check ownership and publish
81
+ await doPublish();
82
+ }, [action, doPublish, isAuthenticated, signIn, t]);
83
+
84
+ const handleForkConfirm = useCallback(async () => {
85
+ setShowForkModal(false);
86
+ setOriginalGroupInfo(null);
87
+ // User confirmed, proceed with publish
88
+ await publish();
89
+ }, [publish]);
90
+
91
+ const handleForkCancel = useCallback(() => {
92
+ setShowForkModal(false);
93
+ setOriginalGroupInfo(null);
94
+ }, []);
95
+
96
+ const buttonTitle = isAuthenticated ? buttonConfig.authenticated : buttonConfig.unauthenticated;
97
+ const loading = isLoading || isCheckingOwnership || isPublishing;
98
+
99
+ return (
100
+ <>
101
+ <Button
102
+ icon={ShapesUploadIcon}
103
+ loading={loading}
104
+ onClick={handleButtonClick}
105
+ title={buttonTitle}
106
+ >
107
+ {t('publishToCommunity')}
108
+ </Button>
109
+ <GroupForkConfirmModal
110
+ loading={isPublishing}
111
+ onCancel={handleForkCancel}
112
+ onConfirm={handleForkConfirm}
113
+ open={showForkModal}
114
+ originalGroup={originalGroupInfo}
115
+ />
116
+ </>
117
+ );
118
+ });
119
+
120
+ PublishButton.displayName = 'GroupPublishButton';
121
+
122
+ export default PublishButton;
@@ -0,0 +1,46 @@
1
+ import isEqual from 'fast-deep-equal';
2
+ import { memo, useCallback, useState } from 'react';
3
+
4
+ import { useAgentGroupStore } from '@/store/agentGroup';
5
+ import { agentGroupSelectors } from '@/store/agentGroup/selectors';
6
+
7
+ import GroupPublishResultModal from './GroupPublishResultModal';
8
+ import PublishButton from './PublishButton';
9
+
10
+ /**
11
+ * Group Publish Button Component
12
+ *
13
+ * Simplified version - backend handles ownership check automatically.
14
+ * The action type (submit vs upload) is determined by backend based on:
15
+ * 1. Whether the identifier exists
16
+ * 2. Whether the current user is the owner
17
+ */
18
+ const GroupPublishButton = memo(() => {
19
+ const currentGroup = useAgentGroupStore(agentGroupSelectors.currentGroup, isEqual);
20
+
21
+ const [showResultModal, setShowResultModal] = useState(false);
22
+ const [publishedIdentifier, setPublishedIdentifier] = useState<string>();
23
+
24
+ const handlePublishSuccess = useCallback((identifier: string) => {
25
+ setPublishedIdentifier(identifier);
26
+ setShowResultModal(true);
27
+ }, []);
28
+
29
+ // Determine action based on whether we have an existing marketIdentifier
30
+ // Backend will verify ownership and decide to create new or update
31
+ // marketIdentifier is stored in editorData
32
+ const action = currentGroup?.editorData?.marketIdentifier ? 'upload' : 'submit';
33
+
34
+ return (
35
+ <>
36
+ <PublishButton action={action} onPublishSuccess={handlePublishSuccess} />
37
+ <GroupPublishResultModal
38
+ identifier={publishedIdentifier}
39
+ onCancel={() => setShowResultModal(false)}
40
+ open={showResultModal}
41
+ />
42
+ </>
43
+ );
44
+ });
45
+
46
+ export default GroupPublishButton;
@@ -0,0 +1,12 @@
1
+ export type MarketPublishAction = 'submit' | 'upload';
2
+
3
+ export interface OriginalGroupInfo {
4
+ author?: {
5
+ avatar?: string;
6
+ name?: string;
7
+ userName?: string;
8
+ };
9
+ avatar?: string;
10
+ identifier: string;
11
+ name: string;
12
+ }
@@ -0,0 +1,211 @@
1
+ import isEqual from 'fast-deep-equal';
2
+ import { useCallback, useRef, useState } from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+
5
+ import { message } from '@/components/AntdStaticMethods';
6
+ import { useMarketAuth } from '@/layout/AuthProvider/MarketAuth';
7
+ import { lambdaClient } from '@/libs/trpc/client';
8
+ import { useAgentGroupStore } from '@/store/agentGroup';
9
+ import { agentGroupSelectors } from '@/store/agentGroup/selectors';
10
+ import { useGlobalStore } from '@/store/global';
11
+ import { globalGeneralSelectors } from '@/store/global/selectors';
12
+
13
+ import type { MarketPublishAction, OriginalGroupInfo } from './types';
14
+ import { generateDefaultChangelog } from './utils';
15
+
16
+ interface UseMarketGroupPublishOptions {
17
+ action: MarketPublishAction;
18
+ onSuccess?: (identifier: string) => void;
19
+ }
20
+
21
+ export interface CheckOwnershipResult {
22
+ needsForkConfirm: boolean;
23
+ originalGroup: OriginalGroupInfo | null;
24
+ }
25
+
26
+ export const useMarketGroupPublish = ({ action, onSuccess }: UseMarketGroupPublishOptions) => {
27
+ const { t } = useTranslation('setting');
28
+ const [isPublishing, setIsPublishing] = useState(false);
29
+ const [isCheckingOwnership, setIsCheckingOwnership] = useState(false);
30
+ const isPublishingRef = useRef(false);
31
+ const { isAuthenticated } = useMarketAuth();
32
+
33
+ // Group data from store
34
+ const currentGroup = useAgentGroupStore(agentGroupSelectors.currentGroup);
35
+ const currentGroupMeta = useAgentGroupStore(agentGroupSelectors.currentGroupMeta, isEqual);
36
+ const currentGroupConfig = useAgentGroupStore(agentGroupSelectors.currentGroupConfig, isEqual);
37
+ const currentGroupAgents = useAgentGroupStore(agentGroupSelectors.currentGroupAgents);
38
+ const updateGroupMeta = useAgentGroupStore((s) => s.updateGroupMeta);
39
+ const language = useGlobalStore(globalGeneralSelectors.currentLanguage);
40
+
41
+ const isSubmit = action === 'submit';
42
+
43
+ /**
44
+ * Check ownership before publishing
45
+ * Returns whether fork confirmation is needed and original group info
46
+ */
47
+ const checkOwnership = useCallback(async (): Promise<CheckOwnershipResult> => {
48
+ // marketIdentifier is stored in editorData
49
+ const identifier = currentGroup?.editorData?.marketIdentifier as string | undefined;
50
+
51
+ // No identifier means new group, no need to check
52
+ if (!identifier) {
53
+ return { needsForkConfirm: false, originalGroup: null };
54
+ }
55
+
56
+ try {
57
+ setIsCheckingOwnership(true);
58
+ const result = await lambdaClient.market.agentGroup.checkOwnership.query({ identifier });
59
+
60
+ // If group doesn't exist or user is owner, no confirmation needed
61
+ if (!result.exists || result.isOwner) {
62
+ return { needsForkConfirm: false, originalGroup: null };
63
+ }
64
+
65
+ // User is not owner, need fork confirmation
66
+ return {
67
+ needsForkConfirm: true,
68
+ originalGroup: result.originalGroup as OriginalGroupInfo,
69
+ };
70
+ } catch (error) {
71
+ console.error('[useMarketGroupPublish] Failed to check ownership:', error);
72
+ // On error, proceed without confirmation
73
+ return { needsForkConfirm: false, originalGroup: null };
74
+ } finally {
75
+ setIsCheckingOwnership(false);
76
+ }
77
+ }, [currentGroup]);
78
+
79
+ const publish = useCallback(async () => {
80
+ // Prevent duplicate publishing
81
+ if (isPublishingRef.current) {
82
+ return { success: false };
83
+ }
84
+
85
+ // Check authentication
86
+ if (!isAuthenticated) {
87
+ return { success: false };
88
+ }
89
+
90
+ if (!currentGroup) {
91
+ message.error({ content: t('marketPublish.modal.messages.noGroup') });
92
+ return { success: false };
93
+ }
94
+
95
+ const messageKey = isSubmit ? 'submit-group' : 'upload-group-version';
96
+ const loadingMessage = isSubmit
97
+ ? t('marketPublish.modal.loading.submitGroup')
98
+ : t('marketPublish.modal.loading.uploadGroup');
99
+
100
+ const changelog = generateDefaultChangelog();
101
+
102
+ try {
103
+ isPublishingRef.current = true;
104
+ setIsPublishing(true);
105
+ message.loading({ content: loadingMessage, key: messageKey });
106
+
107
+ // Prepare member agents data
108
+ const memberAgents = currentGroupAgents.map((agent, index) => ({
109
+ // Only include avatar if it's not null/undefined
110
+ ...(agent.avatar ? { avatar: agent.avatar } : {}),
111
+ config: {
112
+ // Include agent configuration
113
+ model: agent.model,
114
+ params: agent.params,
115
+ systemRole: agent.systemRole,
116
+ },
117
+ // Market requires at least 1 character for description
118
+ description: agent.description || 'No description provided',
119
+ displayOrder: index,
120
+ identifier: agent.id, // Use local agent ID as identifier
121
+ name: agent.title || 'Untitled Agent',
122
+ role: agent.isSupervisor ? ('supervisor' as const) : ('participant' as const),
123
+ // TODO: Construct proper A2A URL for the agent
124
+ url: `https://api.lobehub.com/a2a/agents/${agent.id}`,
125
+ }));
126
+
127
+ // Use tRPC publishOrCreate
128
+ const result = await lambdaClient.market.agentGroup.publishOrCreate.mutate({
129
+ // Only include avatar if it's not null/undefined
130
+ ...(currentGroupMeta.avatar ? { avatar: currentGroupMeta.avatar } : {}),
131
+ // Only include backgroundColor if it's not null/undefined
132
+ ...(currentGroup.backgroundColor ? { backgroundColor: currentGroup.backgroundColor } : {}),
133
+ category: 'productivity', // TODO: Allow user to select category
134
+ changelog,
135
+ // Include group-level config (systemPrompt from content, openingMessage, etc.)
136
+ config: {
137
+ // Group systemPrompt is stored in currentGroup.content
138
+ ...(currentGroup.content !== undefined &&
139
+ currentGroup.content !== null && {
140
+ systemPrompt: currentGroup.content,
141
+ }),
142
+ ...(currentGroupConfig.openingMessage !== undefined && {
143
+ openingMessage: currentGroupConfig.openingMessage,
144
+ }),
145
+ ...(currentGroupConfig.openingQuestions !== undefined &&
146
+ currentGroupConfig.openingQuestions.length > 0 && {
147
+ openingQuestions: currentGroupConfig.openingQuestions,
148
+ }),
149
+ ...(currentGroupConfig.allowDM !== undefined && { allowDM: currentGroupConfig.allowDM }),
150
+ ...(currentGroupConfig.revealDM !== undefined && { revealDM: currentGroupConfig.revealDM }),
151
+ },
152
+ // Market requires at least 1 character for description
153
+ description: currentGroupMeta.description || 'No description provided',
154
+ // marketIdentifier is stored in editorData
155
+ identifier: currentGroup.editorData?.marketIdentifier as string | undefined,
156
+ memberAgents,
157
+ name: currentGroupMeta.title || 'Untitled Group',
158
+ visibility: 'public', // TODO: Allow user to select visibility
159
+ });
160
+
161
+ // Save marketIdentifier to editorData if new group
162
+ if (result.isNewGroup) {
163
+ await updateGroupMeta({
164
+ editorData: {
165
+ ...currentGroup.editorData,
166
+ marketIdentifier: result.identifier,
167
+ },
168
+ });
169
+ }
170
+
171
+ message.success({
172
+ content: t('submitAgentModal.success'),
173
+ key: messageKey,
174
+ });
175
+
176
+ onSuccess?.(result.identifier);
177
+ return { identifier: result.identifier, success: true };
178
+ } catch (error) {
179
+ const errorMessage =
180
+ error instanceof Error ? error.message : t('unknownError', { ns: 'common' });
181
+ message.error({
182
+ content: t('marketPublish.modal.messages.publishFailed', {
183
+ message: errorMessage,
184
+ }),
185
+ key: messageKey,
186
+ });
187
+ return { success: false };
188
+ } finally {
189
+ isPublishingRef.current = false;
190
+ setIsPublishing(false);
191
+ }
192
+ }, [
193
+ currentGroup,
194
+ currentGroupAgents,
195
+ currentGroupConfig,
196
+ currentGroupMeta,
197
+ isAuthenticated,
198
+ isSubmit,
199
+ language,
200
+ onSuccess,
201
+ t,
202
+ updateGroupMeta,
203
+ ]);
204
+
205
+ return {
206
+ checkOwnership,
207
+ isCheckingOwnership,
208
+ isPublishing,
209
+ publish,
210
+ };
211
+ };
@@ -0,0 +1,22 @@
1
+ import { customAlphabet } from 'nanoid/non-secure';
2
+
3
+ /**
4
+ * Generate a market identifier (8-character lowercase alphanumeric string)
5
+ * Format: [a-z0-9]{8}
6
+ * @returns A unique 8-character market identifier
7
+ */
8
+ export const generateMarketIdentifier = () => {
9
+ const alphabet = '0123456789abcdefghijklmnopqrstuvwxyz';
10
+ const generate = customAlphabet(alphabet, 8);
11
+ return generate();
12
+ };
13
+
14
+ /**
15
+ * Generate a default changelog based on current timestamp
16
+ * @returns A timestamp-based changelog string
17
+ */
18
+ export const generateDefaultChangelog = () => {
19
+ const now = new Date();
20
+ const formattedDate = now.toISOString().split('T')[0];
21
+ return `Release ${formattedDate}`;
22
+ };
@@ -168,6 +168,13 @@ export const desktopRoutes: RouteConfig[] = [
168
168
  ),
169
169
  path: 'assistant/:slug',
170
170
  },
171
+ {
172
+ element: dynamicElement(
173
+ () => import('../(main)/community/(detail)/group_agent'),
174
+ 'Desktop > Discover > Detail > Group Agent',
175
+ ),
176
+ path: 'group_agent/:slug',
177
+ },
171
178
  {
172
179
  element: dynamicElement(
173
180
  () => import('../(main)/community/(detail)/model'),
@@ -187,9 +187,13 @@ export default {
187
187
  'llm.waitingForMoreLinkAriaLabel': 'Open the Provider request form',
188
188
  'marketPublish.forkConfirm.by': 'by {{author}}',
189
189
  'marketPublish.forkConfirm.confirm': 'Confirm Publish',
190
+ 'marketPublish.forkConfirm.confirmGroup': 'Confirm Publish',
190
191
  'marketPublish.forkConfirm.description':
191
192
  'You are about to publish a derivative version based on an existing agent from the community. Your new agent will be created as a separate entry in the marketplace.',
193
+ 'marketPublish.forkConfirm.descriptionGroup':
194
+ 'You are about to publish a derivative version based on an existing group from the community. Your new group will be created as a separate entry in the marketplace.',
192
195
  'marketPublish.forkConfirm.title': 'Publish Derivative Agent',
196
+ 'marketPublish.forkConfirm.titleGroup': 'Publish Derivative Group',
193
197
  'marketPublish.modal.changelog.extra':
194
198
  'Describe the key changes and improvements in this version',
195
199
  'marketPublish.modal.changelog.label': 'Changelog',
@@ -209,11 +213,14 @@ export default {
209
213
  'marketPublish.modal.identifier.required': 'Please enter the agent identifier',
210
214
  'marketPublish.modal.loading.fetchingRemote': 'Loading remote data...',
211
215
  'marketPublish.modal.loading.submit': 'Submitting Agent...',
216
+ 'marketPublish.modal.loading.submitGroup': 'Submitting Group...',
212
217
  'marketPublish.modal.loading.upload': 'Publishing new version...',
218
+ 'marketPublish.modal.loading.uploadGroup': 'Publishing new group version...',
213
219
  'marketPublish.modal.messages.createVersionFailed': 'Failed to create version: {{message}}',
214
220
  'marketPublish.modal.messages.fetchRemoteFailed': 'Failed to fetch remote agent data',
215
221
  'marketPublish.modal.messages.missingIdentifier':
216
222
  'This Agent doesn’t have a Community identifier yet.',
223
+ 'marketPublish.modal.messages.noGroup': 'No group selected',
217
224
  'marketPublish.modal.messages.notAuthenticated': 'Sign in to your Community account first.',
218
225
  'marketPublish.modal.messages.publishFailed': 'Publish failed: {{message}}',
219
226
  'marketPublish.modal.submitButton': 'Publish',
@@ -221,12 +228,16 @@ export default {
221
228
  'marketPublish.modal.title.upload': 'Publish New Version',
222
229
  'marketPublish.resultModal.message':
223
230
  'Your Agent has been submitted for review. Once approved, it will go live automatically.',
231
+ 'marketPublish.resultModal.messageGroup':
232
+ 'Your Group has been submitted for review. Once approved, it will go live automatically.',
224
233
  'marketPublish.resultModal.title': 'Submission Successful',
225
234
  'marketPublish.resultModal.view': 'View in Community',
226
235
  'marketPublish.submit.button': 'Share to Community',
227
236
  'marketPublish.submit.tooltip': 'Share this Agent to the Community',
237
+ 'marketPublish.submitGroup.tooltip': 'Share this Group to the Community',
228
238
  'marketPublish.upload.button': 'Publish New Version',
229
239
  'marketPublish.upload.tooltip': 'Publish a new version to Agent Community',
240
+ 'marketPublish.uploadGroup.tooltip': 'Publish a new version to Group Community',
230
241
  'memory.enabled.desc':
231
242
  'Allow LobeHub to extract preferences and info from conversations and use them later. You can view, edit, or clear memory anytime.',
232
243
  'memory.enabled.title': 'Enable Memory',
@@ -551,6 +562,7 @@ export default {
551
562
  'submitAgentModal.placeholder': 'Enter a unique identifier for the agent, e.g. web-development',
552
563
  'submitAgentModal.success': 'Agent submitted successfully',
553
564
  'submitAgentModal.tooltips': 'Share to Agent Community',
565
+ 'submitGroupModal.tooltips': 'Share to Group Community',
554
566
  'sync.device.deviceName.hint': 'Add a name for easy identification',
555
567
  'sync.device.deviceName.placeholder': 'Enter device name',
556
568
  'sync.device.deviceName.title': 'Device Name',