@lobehub/lobehub 2.0.0-next.276 → 2.0.0-next.278
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/.cursor/rules/db-migrations.mdc +1 -1
- package/.cursor/rules/debug-usage.mdc +7 -5
- package/.cursor/rules/desktop-controller-tests.mdc +2 -1
- package/.cursor/rules/desktop-feature-implementation.mdc +9 -5
- package/.cursor/rules/desktop-local-tools-implement.mdc +67 -66
- package/.cursor/rules/desktop-menu-configuration.mdc +21 -9
- package/.cursor/rules/desktop-window-management.mdc +17 -2
- package/.cursor/rules/drizzle-schema-style-guide.mdc +6 -6
- package/.cursor/rules/hotkey.mdc +1 -0
- package/.cursor/rules/i18n.mdc +1 -0
- package/.cursor/rules/project-structure.mdc +16 -3
- package/.cursor/rules/react.mdc +17 -5
- package/.cursor/rules/recent-data-usage.mdc +2 -1
- package/.cursor/rules/testing-guide/testing-guide.mdc +262 -238
- package/.cursor/rules/testing-guide/zustand-store-action-test.mdc +1 -1
- package/.cursor/rules/zustand-action-patterns.mdc +1 -1
- package/.cursor/rules/zustand-slice-organization.mdc +4 -4
- package/CHANGELOG.md +51 -0
- package/CLAUDE.md +1 -1
- package/GEMINI.md +1 -1
- package/changelog/v1.json +14 -0
- package/docs/development/database-schema.dbml +16 -0
- package/locales/en-US/chat.json +24 -0
- package/locales/en-US/setting.json +11 -0
- package/locales/zh-CN/chat.json +24 -0
- package/locales/zh-CN/setting.json +11 -0
- package/package.json +1 -1
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/BatchCreateAgents/index.tsx +2 -2
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/UpdateGroup/index.tsx +56 -56
- package/packages/builtin-tool-group-agent-builder/src/client/Render/BatchCreateAgents.tsx +3 -2
- package/packages/builtin-tool-group-agent-builder/src/executor.ts +2 -1
- package/packages/business/const/src/index.ts +3 -0
- package/packages/database/migrations/0069_add_topic_shares_table.sql +22 -0
- package/packages/database/migrations/meta/0069_snapshot.json +9704 -0
- package/packages/database/migrations/meta/_journal.json +7 -0
- package/packages/database/src/models/__tests__/topicShare.test.ts +318 -0
- package/packages/database/src/models/topicShare.ts +177 -0
- package/packages/database/src/schemas/topic.ts +44 -2
- package/packages/types/src/agentCronJob/index.ts +19 -23
- package/packages/types/src/conversation.ts +5 -0
- package/packages/types/src/serverConfig.ts +1 -0
- package/packages/types/src/topic/topic.ts +46 -0
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Cron/Actions.tsx +31 -0
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Cron/CronTopicGroup.tsx +10 -6
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Cron/index.tsx +7 -11
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Cron/useDropdownMenu.tsx +102 -0
- package/src/app/[variants]/(main)/agent/cron/[cronId]/CronConfig.ts +179 -0
- package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobContentEditor.tsx +111 -0
- package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobHeader.tsx +45 -0
- package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobSaveButton.tsx +31 -0
- package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobScheduleConfig.tsx +213 -0
- package/src/app/[variants]/(main)/agent/cron/[cronId]/index.tsx +186 -344
- package/src/app/[variants]/(main)/agent/features/Conversation/Header/ShareButton/index.tsx +24 -9
- package/src/app/[variants]/(main)/agent/profile/features/AgentCronJobs/index.tsx +42 -97
- package/src/app/[variants]/(main)/agent/profile/features/ProfileEditor/index.tsx +4 -20
- package/src/app/[variants]/(main)/community/features/UserAvatar/index.tsx +15 -5
- package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/AgentProfilePopup.tsx +1 -6
- package/src/app/[variants]/(main)/group/features/Conversation/Header/ShareButton/index.tsx +26 -9
- package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/AspectRatioSelect/index.tsx +1 -2
- package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/ImageNum.tsx +54 -173
- package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/ResolutionSelect.tsx +22 -67
- package/src/app/[variants]/(mobile)/router/mobileRouter.config.tsx +18 -0
- package/src/app/[variants]/router/desktopRouter.config.tsx +18 -0
- package/src/app/[variants]/share/t/[id]/SharedMessageList.tsx +54 -0
- package/src/app/[variants]/share/t/[id]/_layout/index.tsx +170 -0
- package/src/app/[variants]/share/t/[id]/features/Portal/index.tsx +66 -0
- package/src/app/[variants]/share/t/[id]/index.tsx +112 -0
- package/src/app/robots.tsx +1 -1
- package/src/business/client/BusinessMobileRoutes.tsx +1 -1
- package/src/features/Conversation/ChatList/index.tsx +12 -5
- package/src/features/Conversation/Messages/AssistantGroup/Tool/Render/index.tsx +8 -4
- package/src/features/Conversation/Messages/AssistantGroup/Tool/index.tsx +15 -10
- package/src/features/Conversation/Messages/AssistantGroup/Tools.tsx +3 -1
- package/src/features/Conversation/Messages/AssistantGroup/components/ContentBlock.tsx +3 -2
- package/src/features/Conversation/Messages/AssistantGroup/components/GroupItem.tsx +2 -2
- package/src/features/Conversation/Messages/Supervisor/components/ContentBlock.tsx +25 -26
- package/src/features/Conversation/Messages/Supervisor/components/Group.tsx +4 -2
- package/src/features/Conversation/Messages/Tool/Tool/index.tsx +16 -12
- package/src/features/Conversation/Messages/Tool/index.tsx +20 -11
- package/src/features/Conversation/Messages/index.tsx +1 -1
- package/src/features/Conversation/store/slices/data/action.ts +2 -1
- package/src/features/SharePopover/index.tsx +215 -0
- package/src/features/SharePopover/style.ts +10 -0
- package/src/libs/next/proxy/define-config.ts +4 -1
- package/src/locales/default/chat.ts +26 -0
- package/src/proxy.ts +1 -0
- package/src/server/globalConfig/index.ts +1 -0
- package/src/server/routers/lambda/__tests__/message.test.ts +152 -0
- package/src/server/routers/lambda/__tests__/share.test.ts +227 -0
- package/src/server/routers/lambda/__tests__/topic.test.ts +174 -0
- package/src/server/routers/lambda/index.ts +2 -0
- package/src/server/routers/lambda/message.ts +37 -4
- package/src/server/routers/lambda/share.ts +55 -0
- package/src/server/routers/lambda/topic.ts +45 -0
- package/src/services/chatGroup/index.ts +1 -4
- package/src/services/message/index.ts +1 -0
- package/src/services/topic/index.ts +16 -0
- package/src/store/serverConfig/selectors.ts +1 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { DraggablePanel } from '@lobehub/ui';
|
|
4
|
+
import { createStyles } from 'antd-style';
|
|
5
|
+
import { memo } from 'react';
|
|
6
|
+
|
|
7
|
+
import { CHAT_PORTAL_TOOL_UI_WIDTH } from '@/const/layoutTokens';
|
|
8
|
+
import { PortalContent } from '@/features/Portal/router';
|
|
9
|
+
import { useChatStore } from '@/store/chat';
|
|
10
|
+
import { chatPortalSelectors } from '@/store/chat/selectors';
|
|
11
|
+
|
|
12
|
+
const useStyles = createStyles(({ css, token }) => ({
|
|
13
|
+
body: css`
|
|
14
|
+
overflow: hidden;
|
|
15
|
+
display: flex;
|
|
16
|
+
flex: 1;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
|
|
19
|
+
height: 0;
|
|
20
|
+
padding-block-end: 12px;
|
|
21
|
+
`,
|
|
22
|
+
content: css`
|
|
23
|
+
position: relative;
|
|
24
|
+
|
|
25
|
+
overflow: hidden;
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
|
|
29
|
+
height: 100%;
|
|
30
|
+
min-height: 100%;
|
|
31
|
+
max-height: 100%;
|
|
32
|
+
|
|
33
|
+
background: ${token.colorBgContainer};
|
|
34
|
+
`,
|
|
35
|
+
drawer: css`
|
|
36
|
+
z-index: 10;
|
|
37
|
+
height: 100%;
|
|
38
|
+
background: ${token.colorBgContainer};
|
|
39
|
+
`,
|
|
40
|
+
}));
|
|
41
|
+
|
|
42
|
+
const SharePortal = memo(() => {
|
|
43
|
+
const { styles } = useStyles();
|
|
44
|
+
const showPortal = useChatStore(chatPortalSelectors.showPortal);
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<DraggablePanel
|
|
48
|
+
className={styles.drawer}
|
|
49
|
+
classNames={{ content: styles.content }}
|
|
50
|
+
defaultSize={{ width: CHAT_PORTAL_TOOL_UI_WIDTH }}
|
|
51
|
+
expand={showPortal}
|
|
52
|
+
expandable={false}
|
|
53
|
+
minWidth={CHAT_PORTAL_TOOL_UI_WIDTH}
|
|
54
|
+
placement="right"
|
|
55
|
+
showHandleWhenCollapsed={false}
|
|
56
|
+
showHandleWideArea={false}
|
|
57
|
+
size={{ height: '100%', width: CHAT_PORTAL_TOOL_UI_WIDTH }}
|
|
58
|
+
>
|
|
59
|
+
<PortalContent renderBody={(body) => <div className={styles.body}>{body}</div>} />
|
|
60
|
+
</DraggablePanel>
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
SharePortal.displayName = 'SharePortal';
|
|
65
|
+
|
|
66
|
+
export default SharePortal;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Flexbox } from '@lobehub/ui';
|
|
4
|
+
import { TRPCClientError } from '@trpc/client';
|
|
5
|
+
import { Button, Result, Skeleton } from 'antd';
|
|
6
|
+
import { createStyles } from 'antd-style';
|
|
7
|
+
import { memo } from 'react';
|
|
8
|
+
import { useTranslation } from 'react-i18next';
|
|
9
|
+
import { useParams } from 'react-router-dom';
|
|
10
|
+
import useSWR from 'swr';
|
|
11
|
+
|
|
12
|
+
import { lambdaClient } from '@/libs/trpc/client';
|
|
13
|
+
|
|
14
|
+
import SharedMessageList from './SharedMessageList';
|
|
15
|
+
|
|
16
|
+
const useStyles = createStyles(({ css }) => ({
|
|
17
|
+
container: css`
|
|
18
|
+
flex: 1;
|
|
19
|
+
`,
|
|
20
|
+
errorContainer: css`
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
align-items: center;
|
|
24
|
+
justify-content: center;
|
|
25
|
+
|
|
26
|
+
min-height: 400px;
|
|
27
|
+
padding: 48px;
|
|
28
|
+
|
|
29
|
+
text-align: center;
|
|
30
|
+
`,
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
const ShareTopicPage = memo(() => {
|
|
34
|
+
const { styles } = useStyles();
|
|
35
|
+
const { t } = useTranslation('chat');
|
|
36
|
+
const { id } = useParams<{ id: string }>();
|
|
37
|
+
|
|
38
|
+
const { data, error, isLoading } = useSWR(
|
|
39
|
+
id ? ['shared-topic', id] : null,
|
|
40
|
+
() => lambdaClient.share.getSharedTopic.query({ shareId: id! }),
|
|
41
|
+
{ revalidateOnFocus: false },
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
if (isLoading) {
|
|
45
|
+
return (
|
|
46
|
+
<Flexbox className={styles.container} gap={16}>
|
|
47
|
+
<Skeleton active paragraph={{ rows: 1 }} title={false} />
|
|
48
|
+
<Skeleton active paragraph={{ rows: 6 }} />
|
|
49
|
+
</Flexbox>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (error) {
|
|
54
|
+
const trpcError = error instanceof TRPCClientError ? error : null;
|
|
55
|
+
const errorCode = trpcError?.data?.code;
|
|
56
|
+
|
|
57
|
+
if (errorCode === 'UNAUTHORIZED') {
|
|
58
|
+
return (
|
|
59
|
+
<Flexbox className={styles.errorContainer}>
|
|
60
|
+
<Result
|
|
61
|
+
extra={
|
|
62
|
+
<Button href="/login" type="primary">
|
|
63
|
+
{t('sharePage.error.unauthorized.action')}
|
|
64
|
+
</Button>
|
|
65
|
+
}
|
|
66
|
+
status="403"
|
|
67
|
+
subTitle={t('sharePage.error.unauthorized.subtitle')}
|
|
68
|
+
title={t('sharePage.error.unauthorized.title')}
|
|
69
|
+
/>
|
|
70
|
+
</Flexbox>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (errorCode === 'FORBIDDEN') {
|
|
75
|
+
return (
|
|
76
|
+
<Flexbox className={styles.errorContainer}>
|
|
77
|
+
<Result
|
|
78
|
+
status="403"
|
|
79
|
+
subTitle={t('sharePage.error.forbidden.subtitle')}
|
|
80
|
+
title={t('sharePage.error.forbidden.title')}
|
|
81
|
+
/>
|
|
82
|
+
</Flexbox>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// NOT_FOUND or other errors
|
|
87
|
+
return (
|
|
88
|
+
<Flexbox className={styles.errorContainer}>
|
|
89
|
+
<Result
|
|
90
|
+
status="404"
|
|
91
|
+
subTitle={t('sharePage.error.notFound.subtitle')}
|
|
92
|
+
title={t('sharePage.error.notFound.title')}
|
|
93
|
+
/>
|
|
94
|
+
</Flexbox>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (!data) return null;
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<Flexbox className={styles.container}>
|
|
102
|
+
<SharedMessageList
|
|
103
|
+
agentId={data.agentId}
|
|
104
|
+
groupId={data.groupId}
|
|
105
|
+
shareId={data.shareId}
|
|
106
|
+
topicId={data.topicId}
|
|
107
|
+
/>
|
|
108
|
+
</Flexbox>
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
export default ShareTopicPage;
|
package/src/app/robots.tsx
CHANGED
|
@@ -15,6 +15,10 @@ import { dataSelectors, useConversationStore } from '../store';
|
|
|
15
15
|
import VirtualizedList from './components/VirtualizedList';
|
|
16
16
|
|
|
17
17
|
export interface ChatListProps {
|
|
18
|
+
/**
|
|
19
|
+
* Disable the actions bar for all messages (e.g., in share page)
|
|
20
|
+
*/
|
|
21
|
+
disableActionsBar?: boolean;
|
|
18
22
|
/**
|
|
19
23
|
* Custom item renderer. If not provided, uses default ChatItem.
|
|
20
24
|
*/
|
|
@@ -29,7 +33,7 @@ export interface ChatListProps {
|
|
|
29
33
|
*
|
|
30
34
|
* Uses ConversationStore for message data and fetching.
|
|
31
35
|
*/
|
|
32
|
-
const ChatList = memo<ChatListProps>(({ welcome, itemContent }) => {
|
|
36
|
+
const ChatList = memo<ChatListProps>(({ disableActionsBar, welcome, itemContent }) => {
|
|
33
37
|
// Fetch messages (SWR key is null when skipFetch is true)
|
|
34
38
|
const context = useConversationStore((s) => s.context);
|
|
35
39
|
const enableUserMemories = useUserStore(settingsSelectors.memoryEnabled);
|
|
@@ -39,9 +43,12 @@ const ChatList = memo<ChatListProps>(({ welcome, itemContent }) => {
|
|
|
39
43
|
]);
|
|
40
44
|
useFetchMessages(context, skipFetch);
|
|
41
45
|
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
// Skip fetching notebook and memories for share pages (they require authentication)
|
|
47
|
+
const isSharePage = !!context.topicShareId;
|
|
48
|
+
|
|
49
|
+
// Fetch notebook documents when topic is selected (skip for share pages)
|
|
50
|
+
useFetchNotebookDocuments(isSharePage ? undefined : context.topicId!);
|
|
51
|
+
useFetchTopicMemories(enableUserMemories && !isSharePage ? context.topicId : undefined);
|
|
45
52
|
|
|
46
53
|
// Use selectors for data
|
|
47
54
|
|
|
@@ -77,7 +84,7 @@ const ChatList = memo<ChatListProps>(({ welcome, itemContent }) => {
|
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
return (
|
|
80
|
-
<MessageActionProvider withSingletonActionsBar>
|
|
87
|
+
<MessageActionProvider withSingletonActionsBar={!disableActionsBar}>
|
|
81
88
|
<VirtualizedList
|
|
82
89
|
dataSource={displayMessageIds}
|
|
83
90
|
// isGenerating={isGenerating}
|
|
@@ -16,6 +16,7 @@ import RejectedResponse from './RejectedResponse';
|
|
|
16
16
|
interface RenderProps {
|
|
17
17
|
apiName: string;
|
|
18
18
|
arguments?: string;
|
|
19
|
+
disableEditing?: boolean;
|
|
19
20
|
identifier: string;
|
|
20
21
|
intervention?: ToolIntervention;
|
|
21
22
|
isArgumentsStreaming?: boolean;
|
|
@@ -43,6 +44,7 @@ const Render = memo<RenderProps>(
|
|
|
43
44
|
toolCallId,
|
|
44
45
|
messageId,
|
|
45
46
|
arguments: requestArgs,
|
|
47
|
+
disableEditing,
|
|
46
48
|
showPluginRender,
|
|
47
49
|
setShowPluginRender,
|
|
48
50
|
identifier,
|
|
@@ -54,7 +56,7 @@ const Render = memo<RenderProps>(
|
|
|
54
56
|
isArgumentsStreaming,
|
|
55
57
|
isToolCalling,
|
|
56
58
|
}) => {
|
|
57
|
-
if (toolMessageId && intervention?.status === 'pending') {
|
|
59
|
+
if (toolMessageId && intervention?.status === 'pending' && !disableEditing) {
|
|
58
60
|
return (
|
|
59
61
|
<Intervention
|
|
60
62
|
apiName={apiName}
|
|
@@ -150,9 +152,11 @@ const Render = memo<RenderProps>(
|
|
|
150
152
|
showPluginRender={showPluginRender}
|
|
151
153
|
toolCallId={toolCallId}
|
|
152
154
|
/>
|
|
153
|
-
|
|
154
|
-
<
|
|
155
|
-
|
|
155
|
+
{!disableEditing && (
|
|
156
|
+
<div>
|
|
157
|
+
<ModeSelector />
|
|
158
|
+
</div>
|
|
159
|
+
)}
|
|
156
160
|
</Flexbox>
|
|
157
161
|
</Suspense>
|
|
158
162
|
);
|
|
@@ -30,6 +30,7 @@ export interface GroupToolProps {
|
|
|
30
30
|
apiName: string;
|
|
31
31
|
arguments?: string;
|
|
32
32
|
assistantMessageId: string;
|
|
33
|
+
disableEditing?: boolean;
|
|
33
34
|
id: string;
|
|
34
35
|
identifier: string;
|
|
35
36
|
intervention?: ToolIntervention;
|
|
@@ -43,6 +44,7 @@ const Tool = memo<GroupToolProps>(
|
|
|
43
44
|
arguments: requestArgs,
|
|
44
45
|
apiName,
|
|
45
46
|
assistantMessageId,
|
|
47
|
+
disableEditing,
|
|
46
48
|
id,
|
|
47
49
|
intervention,
|
|
48
50
|
identifier,
|
|
@@ -106,16 +108,18 @@ const Tool = memo<GroupToolProps>(
|
|
|
106
108
|
return (
|
|
107
109
|
<AccordionItem
|
|
108
110
|
action={
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
111
|
+
!disableEditing && (
|
|
112
|
+
<Actions
|
|
113
|
+
assistantMessageId={assistantMessageId}
|
|
114
|
+
handleExpand={handleExpand}
|
|
115
|
+
identifier={identifier}
|
|
116
|
+
setShowDebug={setShowDebug}
|
|
117
|
+
setShowPluginRender={setShowPluginRender}
|
|
118
|
+
showCustomPluginRender={showCustomPluginRender}
|
|
119
|
+
showDebug={showDebug}
|
|
120
|
+
showPluginRender={showPluginRender}
|
|
121
|
+
/>
|
|
122
|
+
)
|
|
119
123
|
}
|
|
120
124
|
allowExpand={hasCustomRender}
|
|
121
125
|
expand={isToolRenderExpand}
|
|
@@ -150,6 +154,7 @@ const Tool = memo<GroupToolProps>(
|
|
|
150
154
|
<Render
|
|
151
155
|
apiName={apiName}
|
|
152
156
|
arguments={requestArgs}
|
|
157
|
+
disableEditing={disableEditing}
|
|
153
158
|
identifier={identifier}
|
|
154
159
|
intervention={intervention}
|
|
155
160
|
isArgumentsStreaming={isArgumentsStreaming}
|
|
@@ -5,11 +5,12 @@ import { memo } from 'react';
|
|
|
5
5
|
import Tool from './Tool';
|
|
6
6
|
|
|
7
7
|
interface ToolsRendererProps {
|
|
8
|
+
disableEditing?: boolean;
|
|
8
9
|
messageId: string;
|
|
9
10
|
tools: ChatToolPayloadWithResult[];
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
export const Tools = memo<ToolsRendererProps>(({ messageId, tools }) => {
|
|
13
|
+
export const Tools = memo<ToolsRendererProps>(({ disableEditing, messageId, tools }) => {
|
|
13
14
|
if (!tools || tools.length === 0) return null;
|
|
14
15
|
|
|
15
16
|
return (
|
|
@@ -19,6 +20,7 @@ export const Tools = memo<ToolsRendererProps>(({ messageId, tools }) => {
|
|
|
19
20
|
apiName={tool.apiName}
|
|
20
21
|
arguments={tool.arguments}
|
|
21
22
|
assistantMessageId={messageId}
|
|
23
|
+
disableEditing={disableEditing}
|
|
22
24
|
id={tool.id}
|
|
23
25
|
identifier={tool.identifier}
|
|
24
26
|
intervention={tool.intervention}
|
|
@@ -14,9 +14,10 @@ import MessageContent from './MessageContent';
|
|
|
14
14
|
|
|
15
15
|
interface ContentBlockProps extends AssistantContentBlock {
|
|
16
16
|
assistantId: string;
|
|
17
|
+
disableEditing?: boolean;
|
|
17
18
|
}
|
|
18
19
|
const ContentBlock = memo<ContentBlockProps>(
|
|
19
|
-
({ id, tools, content, imageList, reasoning, error, assistantId }) => {
|
|
20
|
+
({ id, tools, content, imageList, reasoning, error, assistantId, disableEditing }) => {
|
|
20
21
|
const errorContent = useErrorContent(error);
|
|
21
22
|
const showImageItems = !!imageList && imageList.length > 0;
|
|
22
23
|
const [isReasoning, deleteMessage, continueGeneration] = useConversationStore((s) => [
|
|
@@ -70,7 +71,7 @@ const ContentBlock = memo<ContentBlockProps>(
|
|
|
70
71
|
{showImageItems && <ImageFileListViewer items={imageList} />}
|
|
71
72
|
|
|
72
73
|
{/* Tools */}
|
|
73
|
-
{hasTools && <Tools messageId={id} tools={tools} />}
|
|
74
|
+
{hasTools && <Tools disableEditing={disableEditing} messageId={id} tools={tools} />}
|
|
74
75
|
</Flexbox>
|
|
75
76
|
);
|
|
76
77
|
},
|
|
@@ -25,10 +25,10 @@ const GroupItem = memo<GroupItemProps>(
|
|
|
25
25
|
toggleMessageEditing(item.id, true);
|
|
26
26
|
}}
|
|
27
27
|
>
|
|
28
|
-
<ContentBlock {...item} assistantId={assistantId} error={error} />
|
|
28
|
+
<ContentBlock {...item} assistantId={assistantId} disableEditing={disableEditing} error={error} />
|
|
29
29
|
</Flexbox>
|
|
30
30
|
) : (
|
|
31
|
-
<ContentBlock {...item} assistantId={assistantId} error={error} />
|
|
31
|
+
<ContentBlock {...item} assistantId={assistantId} disableEditing={disableEditing} error={error} />
|
|
32
32
|
);
|
|
33
33
|
},
|
|
34
34
|
isEqual,
|
|
@@ -11,34 +11,33 @@ import { Tools } from '../../AssistantGroup/Tools';
|
|
|
11
11
|
import Reasoning from '../../components/Reasoning';
|
|
12
12
|
import MessageContent from './MessageContent';
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
errorContent && error && (content === LOADING_FLAT || !content) ? errorContent : undefined
|
|
26
|
-
}
|
|
27
|
-
id={id}
|
|
28
|
-
/>
|
|
29
|
-
);
|
|
14
|
+
interface ContentBlockProps extends AssistantContentBlock {
|
|
15
|
+
disableEditing?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const ContentBlock = memo<ContentBlockProps>(
|
|
19
|
+
({ id, tools, content, reasoning, error, disableEditing }) => {
|
|
20
|
+
const errorContent = useErrorContent(error);
|
|
21
|
+
const isReasoning = useConversationStore(messageStateSelectors.isMessageInReasoning(id));
|
|
22
|
+
const hasTools = tools && tools.length > 0;
|
|
23
|
+
const showReasoning =
|
|
24
|
+
(!!reasoning && reasoning.content?.trim() !== '') || (!reasoning && isReasoning);
|
|
30
25
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
{showReasoning && <Reasoning {...reasoning} id={id} />}
|
|
26
|
+
if (error && (content === LOADING_FLAT || !content))
|
|
27
|
+
return <ErrorContent error={errorContent} id={id} />;
|
|
34
28
|
|
|
35
|
-
|
|
36
|
-
<
|
|
29
|
+
return (
|
|
30
|
+
<Flexbox gap={8} id={id}>
|
|
31
|
+
{showReasoning && <Reasoning {...reasoning} id={id} />}
|
|
32
|
+
|
|
33
|
+
{/* Content - markdown text */}
|
|
34
|
+
<MessageContent content={content} hasTools={hasTools} id={id} />
|
|
37
35
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
36
|
+
{/* Tools */}
|
|
37
|
+
{hasTools && <Tools disableEditing={disableEditing} messageId={id} tools={tools} />}
|
|
38
|
+
</Flexbox>
|
|
39
|
+
);
|
|
40
|
+
},
|
|
41
|
+
);
|
|
43
42
|
|
|
44
43
|
export default ContentBlock;
|
|
@@ -29,7 +29,7 @@ interface GroupChildrenProps {
|
|
|
29
29
|
messageIndex: number;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const Group = memo<GroupChildrenProps>(({ blocks, id, content }) => {
|
|
32
|
+
const Group = memo<GroupChildrenProps>(({ blocks, id, content, disableEditing }) => {
|
|
33
33
|
const isCollapsed = useConversationStore(messageStateSelectors.isMessageCollapsed(id));
|
|
34
34
|
const contextValue = useMemo(() => ({ assistantGroupId: id }), [id]);
|
|
35
35
|
|
|
@@ -46,7 +46,9 @@ const Group = memo<GroupChildrenProps>(({ blocks, id, content }) => {
|
|
|
46
46
|
<MessageAggregationContext value={contextValue}>
|
|
47
47
|
<Flexbox className={styles.container} gap={8}>
|
|
48
48
|
{blocks.map((item) => {
|
|
49
|
-
return
|
|
49
|
+
return (
|
|
50
|
+
<ContentBlock {...item} disableEditing={disableEditing} key={id + '.' + item.id} />
|
|
51
|
+
);
|
|
50
52
|
})}
|
|
51
53
|
</Flexbox>
|
|
52
54
|
</MessageAggregationContext>
|
|
@@ -20,6 +20,7 @@ const Render = dynamic(() => import('../../AssistantGroup/Tool/Render'), {
|
|
|
20
20
|
export interface InspectorProps {
|
|
21
21
|
apiName: string;
|
|
22
22
|
arguments?: string;
|
|
23
|
+
disableEditing?: boolean;
|
|
23
24
|
identifier: string;
|
|
24
25
|
index: number;
|
|
25
26
|
messageId: string;
|
|
@@ -32,7 +33,7 @@ export interface InspectorProps {
|
|
|
32
33
|
* Tool message component - adapts Tool message data to use AssistantGroup/Tool components
|
|
33
34
|
*/
|
|
34
35
|
const Tool = memo<InspectorProps>(
|
|
35
|
-
({ arguments: requestArgs, apiName, messageId, toolCallId, index, identifier, type }) => {
|
|
36
|
+
({ arguments: requestArgs, apiName, disableEditing, messageId, toolCallId, index, identifier, type }) => {
|
|
36
37
|
const [showDebug, setShowDebug] = useState(false);
|
|
37
38
|
const [showPluginRender, setShowPluginRender] = useState(false);
|
|
38
39
|
const [expand, setExpand] = useState(true);
|
|
@@ -66,16 +67,18 @@ const Tool = memo<InspectorProps>(
|
|
|
66
67
|
>
|
|
67
68
|
<AccordionItem
|
|
68
69
|
action={
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
70
|
+
!disableEditing && (
|
|
71
|
+
<Actions
|
|
72
|
+
assistantMessageId={messageId}
|
|
73
|
+
handleExpand={(expand) => setExpand(!!expand)}
|
|
74
|
+
identifier={identifier}
|
|
75
|
+
setShowDebug={setShowDebug}
|
|
76
|
+
setShowPluginRender={setShowPluginRender}
|
|
77
|
+
showCustomPluginRender={false}
|
|
78
|
+
showDebug={showDebug}
|
|
79
|
+
showPluginRender={showPluginRender}
|
|
80
|
+
/>
|
|
81
|
+
)
|
|
79
82
|
}
|
|
80
83
|
itemKey={'tool'}
|
|
81
84
|
paddingBlock={4}
|
|
@@ -83,7 +86,7 @@ const Tool = memo<InspectorProps>(
|
|
|
83
86
|
title={<Inspectors apiName={apiName} identifier={identifier} result={result} />}
|
|
84
87
|
>
|
|
85
88
|
<Flexbox gap={8} paddingBlock={8}>
|
|
86
|
-
{showDebug && (
|
|
89
|
+
{showDebug && !disableEditing && (
|
|
87
90
|
<Debug
|
|
88
91
|
apiName={apiName}
|
|
89
92
|
identifier={identifier}
|
|
@@ -96,6 +99,7 @@ const Tool = memo<InspectorProps>(
|
|
|
96
99
|
<Render
|
|
97
100
|
apiName={apiName}
|
|
98
101
|
arguments={requestArgs}
|
|
102
|
+
disableEditing={disableEditing}
|
|
99
103
|
identifier={identifier}
|
|
100
104
|
messageId={messageId}
|
|
101
105
|
result={result}
|
|
@@ -8,11 +8,12 @@ import { dataSelectors, useConversationStore } from '../../store';
|
|
|
8
8
|
import Tool from './Tool';
|
|
9
9
|
|
|
10
10
|
interface ToolMessageProps {
|
|
11
|
+
disableEditing?: boolean;
|
|
11
12
|
id: string;
|
|
12
13
|
index: number;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
const ToolMessage = memo<ToolMessageProps>(({ id, index }) => {
|
|
16
|
+
const ToolMessage = memo<ToolMessageProps>(({ disableEditing, id, index }) => {
|
|
16
17
|
const { t } = useTranslation('plugin');
|
|
17
18
|
const item = useConversationStore(dataSelectors.getDbMessageById(id), isEqual) as UIChatMessage;
|
|
18
19
|
const deleteToolMessage = useConversationStore((s) => s.deleteToolMessage);
|
|
@@ -29,17 +30,25 @@ const ToolMessage = memo<ToolMessageProps>(({ id, index }) => {
|
|
|
29
30
|
|
|
30
31
|
return (
|
|
31
32
|
<Flexbox gap={4} paddingBlock={12}>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
{
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
{!disableEditing && (
|
|
34
|
+
<Alert
|
|
35
|
+
action={
|
|
36
|
+
<Button loading={loading} onClick={handleDelete} size={'small'} type={'primary'}>
|
|
37
|
+
{t('inspector.delete')}
|
|
38
|
+
</Button>
|
|
39
|
+
}
|
|
40
|
+
title={t('inspector.orphanedToolCall')}
|
|
41
|
+
type={'secondary'}
|
|
42
|
+
/>
|
|
43
|
+
)}
|
|
41
44
|
{item.plugin && (
|
|
42
|
-
<Tool
|
|
45
|
+
<Tool
|
|
46
|
+
{...item.plugin}
|
|
47
|
+
disableEditing={disableEditing}
|
|
48
|
+
index={index}
|
|
49
|
+
messageId={id}
|
|
50
|
+
toolCallId={item.tool_call_id!}
|
|
51
|
+
/>
|
|
43
52
|
)}
|
|
44
53
|
</Flexbox>
|
|
45
54
|
);
|
|
@@ -103,13 +103,14 @@ export const dataSlice: StateCreator<
|
|
|
103
103
|
useFetchMessages: (context, skipFetch) => {
|
|
104
104
|
// When skipFetch is true, SWR key is null - no fetch occurs
|
|
105
105
|
// This is used when external messages are provided (e.g., creating new thread)
|
|
106
|
+
// Allow fetch if: has agentId (both agent topics and group topics have agentId)
|
|
106
107
|
const shouldFetch = !skipFetch && !!context.agentId;
|
|
107
108
|
|
|
108
109
|
return useClientDataSWRWithSync<UIChatMessage[]>(
|
|
109
110
|
shouldFetch ? ['CONVERSATION_FETCH_MESSAGES', context] : null,
|
|
110
111
|
|
|
111
112
|
async () => {
|
|
112
|
-
return messageService.getMessages(context
|
|
113
|
+
return messageService.getMessages(context);
|
|
113
114
|
},
|
|
114
115
|
{
|
|
115
116
|
onData: (data) => {
|