@lobehub/lobehub 2.0.0-next.295 → 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.
- package/CHANGELOG.md +50 -0
- package/changelog/v1.json +18 -0
- package/locales/en-US/plugin.json +4 -0
- package/locales/zh-CN/plugin.json +4 -0
- package/package.json +2 -2
- package/packages/agent-runtime/src/core/__tests__/runtime.test.ts +5 -5
- package/packages/agent-runtime/src/utils/stepContextComputer.test.ts +5 -5
- package/packages/builtin-tool-gtd/src/client/Inspector/index.ts +0 -4
- package/packages/builtin-tool-gtd/src/client/Intervention/AddTodo.tsx +1 -1
- package/packages/builtin-tool-gtd/src/client/Render/TodoList/index.tsx +39 -10
- package/packages/builtin-tool-gtd/src/client/Render/index.ts +0 -2
- package/packages/builtin-tool-gtd/src/client/components/SortableTodoList/TodoItemRow.tsx +26 -12
- package/packages/builtin-tool-gtd/src/client/components/SortableTodoList/store/actions.ts +5 -5
- package/packages/builtin-tool-gtd/src/client/components/SortableTodoList/store/store.test.ts +14 -8
- package/packages/builtin-tool-gtd/src/executor/index.test.ts +48 -227
- package/packages/builtin-tool-gtd/src/executor/index.ts +15 -158
- package/packages/builtin-tool-gtd/src/manifest.ts +12 -42
- package/packages/builtin-tool-gtd/src/systemRole.ts +14 -8
- package/packages/builtin-tool-gtd/src/types.ts +47 -41
- package/packages/builtin-tool-memory/package.json +8 -0
- package/packages/builtin-tool-memory/src/client/Inspector/AddContextMemory/index.tsx +60 -0
- package/packages/builtin-tool-memory/src/client/Inspector/AddExperienceMemory/index.tsx +60 -0
- package/packages/builtin-tool-memory/src/client/Inspector/AddIdentityMemory/index.tsx +60 -0
- package/packages/builtin-tool-memory/src/client/Inspector/AddPreferenceMemory/index.tsx +60 -0
- package/packages/builtin-tool-memory/src/client/Inspector/RemoveIdentityMemory/index.tsx +60 -0
- package/packages/builtin-tool-memory/src/client/Inspector/SearchUserMemory/index.tsx +67 -0
- package/packages/builtin-tool-memory/src/client/Inspector/UpdateIdentityMemory/index.tsx +60 -0
- package/packages/builtin-tool-memory/src/client/Inspector/index.ts +35 -0
- package/packages/builtin-tool-memory/src/client/Intervention/AddExperienceMemory/index.tsx +17 -0
- package/packages/builtin-tool-memory/src/client/Intervention/index.ts +13 -0
- package/packages/builtin-tool-memory/src/client/Render/AddExperienceMemory/index.tsx +17 -0
- package/packages/builtin-tool-memory/src/client/Render/SearchUserMemory/index.tsx +217 -0
- package/packages/builtin-tool-memory/src/client/Render/index.ts +15 -0
- package/packages/builtin-tool-memory/src/client/Streaming/AddExperienceMemory/index.tsx +17 -0
- package/packages/builtin-tool-memory/src/client/Streaming/index.ts +18 -0
- package/packages/builtin-tool-memory/src/client/components/ExperienceMemoryCard.tsx +231 -0
- package/packages/builtin-tool-memory/src/client/components/index.ts +1 -0
- package/packages/builtin-tool-memory/src/client/index.ts +27 -0
- package/packages/builtin-tool-memory/src/executor/index.ts +9 -1
- package/packages/builtin-tool-memory/src/types.ts +61 -0
- package/packages/context-engine/src/providers/GTDTodoInjector.ts +15 -7
- package/packages/conversation-flow/src/__tests__/fixtures/outputs/assistantGroup/tools-with-branches.json +4 -0
- package/packages/conversation-flow/src/transformation/FlatListBuilder.ts +1 -0
- package/packages/prompts/src/prompts/gtd/index.test.ts +32 -16
- package/packages/prompts/src/prompts/gtd/index.ts +9 -5
- package/packages/types/package.json +1 -1
- package/packages/types/src/discover/assistants.ts +4 -0
- package/packages/types/src/discover/groupAgents.ts +196 -0
- package/packages/types/src/discover/index.ts +5 -1
- package/packages/types/src/stepContext.ts +4 -1
- package/src/app/[variants]/(main)/community/(detail)/assistant/features/Details/Versions/index.tsx +2 -2
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/DetailProvider.tsx +19 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Members/index.tsx +137 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Nav.tsx +88 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Overview/index.tsx +213 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Related/index.tsx +85 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/SystemRole/TagList.tsx +20 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/SystemRole/index.tsx +71 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Versions/index.tsx +119 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/index.tsx +51 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Header.tsx +253 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/ActionButton/AddGroupAgent.tsx +222 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/ActionButton/index.tsx +34 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/Summary/index.tsx +42 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/index.tsx +41 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/StatusPage/index.tsx +104 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/index.tsx +103 -0
- package/src/app/[variants]/(main)/community/(detail)/group_agent/loading.tsx +1 -0
- package/src/app/[variants]/(main)/community/(detail)/user/features/DetailProvider.tsx +7 -1
- package/src/app/[variants]/(main)/community/(detail)/user/features/UserContent.tsx +2 -0
- package/src/app/[variants]/(main)/community/(detail)/user/features/UserGroupCard.tsx +186 -0
- package/src/app/[variants]/(main)/community/(detail)/user/features/UserGroupList.tsx +59 -0
- package/src/app/[variants]/(main)/community/(detail)/user/index.tsx +3 -1
- package/src/app/[variants]/(main)/community/(list)/assistant/features/List/Item.tsx +26 -8
- package/src/app/[variants]/(main)/community/(list)/assistant/index.tsx +1 -0
- package/src/app/[variants]/(main)/community/features/Search.tsx +1 -1
- package/src/app/[variants]/(main)/group/profile/features/GroupProfile/index.tsx +2 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/AgentPublishButton/PublishResultModal.tsx +2 -1
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/GroupForkConfirmModal.tsx +60 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/GroupPublishResultModal.tsx +62 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/PublishButton.tsx +122 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/index.tsx +46 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/types.ts +12 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/useMarketGroupPublish.ts +211 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/utils.ts +22 -0
- package/src/app/[variants]/(main)/resource/features/DndContextWrapper.tsx +4 -2
- package/src/app/[variants]/(main)/resource/library/_layout/Header/LibraryHead.tsx +30 -35
- package/src/app/[variants]/(main)/resource/library/_layout/Header/index.tsx +9 -11
- package/src/app/[variants]/router/desktopRouter.config.tsx +7 -0
- package/src/features/Conversation/Messages/AssistantGroup/Tool/Actions/index.tsx +11 -17
- package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/LoadingPlaceholder/index.tsx +13 -3
- package/src/features/Conversation/Messages/AssistantGroup/Tool/Detail/Render/CustomRender.tsx +43 -0
- package/src/features/Conversation/Messages/AssistantGroup/Tool/Detail/Render/FallbacktArgumentRender.tsx +59 -0
- package/src/features/Conversation/Messages/AssistantGroup/Tool/Detail/Render/index.tsx +46 -0
- package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/index.tsx +13 -19
- package/src/features/Conversation/Messages/AssistantGroup/Tool/index.tsx +17 -17
- package/src/features/Conversation/Messages/Tool/Tool/index.tsx +10 -9
- package/src/features/Conversation/TodoProgress/index.tsx +56 -23
- package/src/features/PluginsUI/Render/MCPType/index.tsx +1 -1
- package/src/features/ResourceManager/components/Explorer/Header/index.tsx +57 -4
- package/src/features/ResourceManager/components/Explorer/ListView/ListItem/index.tsx +6 -4
- package/src/features/ResourceManager/components/Explorer/ListView/index.tsx +16 -5
- package/src/features/ResourceManager/components/LibraryHierarchy/styles.ts +5 -4
- package/src/hooks/useActiveTabKey.ts +1 -2
- package/src/locales/default/plugin.ts +1 -0
- package/src/locales/default/setting.ts +12 -0
- package/src/server/routers/lambda/market/agentGroup.ts +296 -0
- package/src/server/routers/lambda/market/index.ts +134 -4
- package/src/server/services/discover/index.ts +123 -7
- package/src/services/discover.ts +55 -0
- package/src/store/chat/slices/message/selectors/dbMessage.test.ts +11 -11
- package/src/store/discover/slices/groupAgent/action.ts +80 -0
- package/src/store/discover/store.ts +3 -0
- package/src/store/file/slices/resource/action.ts +4 -2
- package/src/tools/inspectors.ts +2 -0
- package/src/tools/interventions.ts +2 -0
- package/src/tools/renders.ts +3 -1
- package/src/tools/streamings.ts +2 -0
- package/packages/builtin-tool-gtd/src/client/Inspector/CompleteTodos/index.tsx +0 -52
- package/packages/builtin-tool-gtd/src/client/Inspector/RemoveTodos/index.tsx +0 -52
- package/src/features/Conversation/Messages/AssistantGroup/Tool/Render/CustomRender.tsx +0 -113
- package/src/features/Conversation/Messages/Tool/Tool/Render.tsx +0 -47
- /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/AbortResponse.tsx +0 -0
- /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Arguments/index.tsx +0 -0
- /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/ErrorResponse.tsx +0 -0
- /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/ApprovalActions.tsx +0 -0
- /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/Fallback.tsx +0 -0
- /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/KeyValueEditor.tsx +0 -0
- /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/ModeSelector.tsx +0 -0
- /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/index.tsx +0 -0
- /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/PluginSettings.tsx +0 -0
- /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/RejectedResponse.tsx +0 -0
|
@@ -14,6 +14,7 @@ import { agentGroupSelectors } from '@/store/agentGroup/selectors';
|
|
|
14
14
|
import { useGroupProfileStore } from '@/store/groupProfile';
|
|
15
15
|
|
|
16
16
|
import AutoSaveHint from '../Header/AutoSaveHint';
|
|
17
|
+
import GroupPublishButton from '../Header/GroupPublishButton';
|
|
17
18
|
import GroupHeader from './GroupHeader';
|
|
18
19
|
|
|
19
20
|
const GroupProfile = memo(() => {
|
|
@@ -75,6 +76,7 @@ const GroupProfile = memo(() => {
|
|
|
75
76
|
>
|
|
76
77
|
{t('startConversation')}
|
|
77
78
|
</Button>
|
|
79
|
+
<GroupPublishButton />
|
|
78
80
|
</Flexbox>
|
|
79
81
|
</Flexbox>
|
|
80
82
|
<Divider />
|
|
@@ -19,7 +19,8 @@ const PublishResultModal = memo<PublishResultModalProps>(({ identifier, onCancel
|
|
|
19
19
|
|
|
20
20
|
const handleGoToMarket = () => {
|
|
21
21
|
if (identifier) {
|
|
22
|
-
|
|
22
|
+
console.log('identifier', identifier);
|
|
23
|
+
navigate(`/community/group_agent/${identifier}`);
|
|
23
24
|
}
|
|
24
25
|
onCancel();
|
|
25
26
|
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Avatar, Flexbox, Modal } from '@lobehub/ui';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
|
|
7
|
+
import type { OriginalGroupInfo } from './types';
|
|
8
|
+
|
|
9
|
+
interface GroupForkConfirmModalProps {
|
|
10
|
+
loading?: boolean;
|
|
11
|
+
onCancel: () => void;
|
|
12
|
+
onConfirm: () => void;
|
|
13
|
+
open: boolean;
|
|
14
|
+
originalGroup: OriginalGroupInfo | null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const GroupForkConfirmModal = memo<GroupForkConfirmModalProps>(
|
|
18
|
+
({ open, onCancel, onConfirm, originalGroup, loading }) => {
|
|
19
|
+
const { t } = useTranslation('setting');
|
|
20
|
+
|
|
21
|
+
if (!originalGroup) return null;
|
|
22
|
+
|
|
23
|
+
const authorName = originalGroup.author?.name || originalGroup.author?.userName || 'Unknown';
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<Modal
|
|
27
|
+
cancelText={t('cancel', { ns: 'common' })}
|
|
28
|
+
centered
|
|
29
|
+
closable
|
|
30
|
+
confirmLoading={loading}
|
|
31
|
+
okText={t('marketPublish.forkConfirm.confirmGroup')}
|
|
32
|
+
onCancel={onCancel}
|
|
33
|
+
onOk={onConfirm}
|
|
34
|
+
open={open}
|
|
35
|
+
title={t('marketPublish.forkConfirm.titleGroup')}
|
|
36
|
+
width={480}
|
|
37
|
+
>
|
|
38
|
+
<Flexbox gap={16} style={{ marginTop: 16 }}>
|
|
39
|
+
<Flexbox align="center" gap={12} horizontal>
|
|
40
|
+
<Avatar avatar={originalGroup.avatar} size={48} style={{ flex: 'none' }} />
|
|
41
|
+
<Flexbox gap={4}>
|
|
42
|
+
<div style={{ fontWeight: 500 }}>{originalGroup.name}</div>
|
|
43
|
+
<div style={{ fontSize: 12, opacity: 0.6 }}>
|
|
44
|
+
{t('marketPublish.forkConfirm.by', { author: authorName })}
|
|
45
|
+
</div>
|
|
46
|
+
</Flexbox>
|
|
47
|
+
</Flexbox>
|
|
48
|
+
|
|
49
|
+
<p style={{ lineHeight: 1.6, margin: 0 }}>
|
|
50
|
+
{t('marketPublish.forkConfirm.descriptionGroup')}
|
|
51
|
+
</p>
|
|
52
|
+
</Flexbox>
|
|
53
|
+
</Modal>
|
|
54
|
+
);
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
GroupForkConfirmModal.displayName = 'GroupForkConfirmModal';
|
|
59
|
+
|
|
60
|
+
export default GroupForkConfirmModal;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { FluentEmoji, Modal, Text } from '@lobehub/ui';
|
|
4
|
+
import { Result } from 'antd';
|
|
5
|
+
import { memo } from 'react';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
import { useNavigate } from 'react-router-dom';
|
|
8
|
+
|
|
9
|
+
interface GroupPublishResultModalProps {
|
|
10
|
+
identifier?: string;
|
|
11
|
+
onCancel: () => void;
|
|
12
|
+
open: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const GroupPublishResultModal = memo<GroupPublishResultModalProps>(
|
|
16
|
+
({ identifier, onCancel, open }) => {
|
|
17
|
+
const navigate = useNavigate();
|
|
18
|
+
const { t } = useTranslation('setting');
|
|
19
|
+
const { t: tCommon } = useTranslation('common');
|
|
20
|
+
|
|
21
|
+
const handleGoToMarket = () => {
|
|
22
|
+
if (identifier) {
|
|
23
|
+
navigate(`/community/group_agent/${identifier}`);
|
|
24
|
+
}
|
|
25
|
+
onCancel();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<Modal
|
|
30
|
+
cancelText={tCommon('cancel')}
|
|
31
|
+
centered
|
|
32
|
+
okText={t('marketPublish.resultModal.view')}
|
|
33
|
+
onCancel={onCancel}
|
|
34
|
+
onOk={handleGoToMarket}
|
|
35
|
+
open={open}
|
|
36
|
+
title={null}
|
|
37
|
+
width={440}
|
|
38
|
+
>
|
|
39
|
+
<Result
|
|
40
|
+
icon={<FluentEmoji emoji={'🎉'} size={96} type={'anim'} />}
|
|
41
|
+
style={{
|
|
42
|
+
paddingBottom: 32,
|
|
43
|
+
paddingTop: 48,
|
|
44
|
+
width: '100%',
|
|
45
|
+
}}
|
|
46
|
+
subTitle={
|
|
47
|
+
<Text fontSize={14} type={'secondary'}>
|
|
48
|
+
{t('marketPublish.resultModal.messageGroup')}
|
|
49
|
+
</Text>
|
|
50
|
+
}
|
|
51
|
+
title={
|
|
52
|
+
<Text fontSize={28} weight={'bold'}>
|
|
53
|
+
{t('marketPublish.resultModal.title')}
|
|
54
|
+
</Text>
|
|
55
|
+
}
|
|
56
|
+
/>
|
|
57
|
+
</Modal>
|
|
58
|
+
);
|
|
59
|
+
},
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
export default GroupPublishResultModal;
|
package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/PublishButton.tsx
ADDED
|
@@ -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,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
|
+
};
|
|
@@ -193,14 +193,16 @@ export const DndContextWrapper = memo<PropsWithChildren>(({ children }) => {
|
|
|
193
193
|
|
|
194
194
|
document.addEventListener('dragstart', handleDragStart);
|
|
195
195
|
document.addEventListener('drag', handleDrag);
|
|
196
|
-
|
|
196
|
+
// Use capture phase so drops still work even if some UI stops propagation
|
|
197
|
+
// (e.g., header dropdowns / menus).
|
|
198
|
+
document.addEventListener('drop', handleDrop, true);
|
|
197
199
|
document.addEventListener('dragover', handleDragOver);
|
|
198
200
|
document.addEventListener('dragend', handleDragEnd);
|
|
199
201
|
|
|
200
202
|
return () => {
|
|
201
203
|
document.removeEventListener('dragstart', handleDragStart);
|
|
202
204
|
document.removeEventListener('drag', handleDrag);
|
|
203
|
-
document.removeEventListener('drop', handleDrop);
|
|
205
|
+
document.removeEventListener('drop', handleDrop, true);
|
|
204
206
|
document.removeEventListener('dragover', handleDragOver);
|
|
205
207
|
document.removeEventListener('dragend', handleDragEnd);
|
|
206
208
|
};
|