@lobehub/lobehub 2.0.0-next.89 → 2.0.0-next.90
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 +25 -0
- package/changelog/v1.json +9 -0
- package/locales/ar/chat.json +4 -0
- package/locales/ar/models.json +3 -6
- package/locales/bg-BG/chat.json +4 -0
- package/locales/bg-BG/models.json +3 -6
- package/locales/de-DE/chat.json +4 -0
- package/locales/de-DE/models.json +3 -6
- package/locales/en-US/chat.json +4 -0
- package/locales/en-US/common.json +1 -0
- package/locales/en-US/models.json +3 -6
- package/locales/es-ES/chat.json +4 -0
- package/locales/es-ES/models.json +3 -6
- package/locales/fa-IR/chat.json +4 -0
- package/locales/fa-IR/models.json +3 -6
- package/locales/fr-FR/chat.json +4 -0
- package/locales/fr-FR/models.json +3 -6
- package/locales/it-IT/chat.json +4 -0
- package/locales/it-IT/models.json +3 -6
- package/locales/ja-JP/chat.json +4 -0
- package/locales/ja-JP/models.json +3 -6
- package/locales/ko-KR/chat.json +4 -0
- package/locales/ko-KR/models.json +3 -6
- package/locales/nl-NL/chat.json +4 -0
- package/locales/nl-NL/models.json +3 -6
- package/locales/pl-PL/chat.json +4 -0
- package/locales/pl-PL/models.json +3 -6
- package/locales/pt-BR/chat.json +4 -0
- package/locales/pt-BR/models.json +3 -6
- package/locales/ru-RU/chat.json +4 -0
- package/locales/ru-RU/models.json +3 -6
- package/locales/tr-TR/chat.json +4 -0
- package/locales/tr-TR/models.json +3 -6
- package/locales/vi-VN/chat.json +4 -0
- package/locales/vi-VN/models.json +3 -6
- package/locales/zh-CN/chat.json +4 -0
- package/locales/zh-CN/common.json +1 -0
- package/locales/zh-CN/models.json +3 -6
- package/locales/zh-TW/chat.json +4 -0
- package/locales/zh-TW/models.json +3 -6
- package/package.json +1 -1
- package/packages/model-bank/src/types/aiModel.ts +1 -0
- package/packages/types/src/message/common/metadata.ts +6 -0
- package/packages/utils/src/time.ts +4 -0
- package/src/app/(backend)/middleware/auth/index.ts +1 -2
- package/src/app/(backend)/webapi/chat/[provider]/route.ts +1 -1
- package/src/app/(backend)/webapi/models/[provider]/pull/route.ts +1 -1
- package/src/app/(backend)/webapi/models/[provider]/route.ts +1 -1
- package/src/app/(backend)/webapi/text-to-image/[provider]/route.ts +1 -1
- package/src/app/[variants]/(main)/settings/provider/features/ModelList/ModelItem.tsx +74 -97
- package/src/features/Conversation/Messages/Group/Tool/Inspector/BuiltinPluginTitle.tsx +22 -11
- package/src/features/Conversation/Messages/Group/Tool/Inspector/StatusIndicator.tsx +41 -0
- package/src/features/Conversation/Messages/Group/Tool/Inspector/ToolTitle.tsx +13 -3
- package/src/features/Conversation/Messages/Group/Tool/Inspector/index.tsx +28 -34
- package/src/features/Conversation/Messages/Group/Tool/Render/AbortResponse.tsx +37 -0
- package/src/features/Conversation/Messages/Group/Tool/Render/index.tsx +6 -0
- package/src/features/Conversation/Messages/Group/Tool/index.tsx +1 -0
- package/src/locales/default/chat.ts +1 -0
- package/src/locales/default/common.ts +1 -0
- package/src/server/routers/lambda/file.ts +0 -6
- package/src/store/chat/slices/message/actions/publicApi.ts +15 -0
|
@@ -18,6 +18,9 @@ export const useStyles = createStyles(({ css, token }) => ({
|
|
|
18
18
|
text-overflow: ellipsis;
|
|
19
19
|
`,
|
|
20
20
|
|
|
21
|
+
expand: css`
|
|
22
|
+
color: ${token.colorText};
|
|
23
|
+
`,
|
|
21
24
|
shinyText: shinyTextStylish(token),
|
|
22
25
|
}));
|
|
23
26
|
|
|
@@ -26,22 +29,30 @@ interface BuiltinPluginTitleProps {
|
|
|
26
29
|
icon?: ReactNode;
|
|
27
30
|
identifier: string;
|
|
28
31
|
index: number;
|
|
32
|
+
isExpanded?: boolean;
|
|
29
33
|
isLoading?: boolean;
|
|
30
34
|
messageId: string;
|
|
31
35
|
title: string;
|
|
32
36
|
toolCallId: string;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
const BuiltinPluginTitle = memo<BuiltinPluginTitleProps>(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
const BuiltinPluginTitle = memo<BuiltinPluginTitleProps>(
|
|
40
|
+
({ apiName, title, isLoading, isExpanded }) => {
|
|
41
|
+
const { styles, cx } = useStyles();
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<Flexbox
|
|
45
|
+
align={'center'}
|
|
46
|
+
className={cx(isLoading && styles.shinyText, isExpanded && styles.expand)}
|
|
47
|
+
gap={4}
|
|
48
|
+
horizontal
|
|
49
|
+
>
|
|
50
|
+
<div>{title}</div>
|
|
51
|
+
<Icon icon={ChevronRight} />
|
|
52
|
+
<span className={styles.apiName}>{apiName}</span>
|
|
53
|
+
</Flexbox>
|
|
54
|
+
);
|
|
55
|
+
},
|
|
56
|
+
);
|
|
46
57
|
|
|
47
58
|
export default BuiltinPluginTitle;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ToolIntervention } from '@lobechat/types';
|
|
2
|
+
import { Icon, Tooltip } from '@lobehub/ui';
|
|
3
|
+
import { useTheme } from 'antd-style';
|
|
4
|
+
import { Ban, Check, CircleStop, X } from 'lucide-react';
|
|
5
|
+
import { memo } from 'react';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
import { Flexbox } from 'react-layout-kit';
|
|
8
|
+
|
|
9
|
+
interface StatusIndicatorProps {
|
|
10
|
+
intervention?: ToolIntervention;
|
|
11
|
+
result?: { content: string | null; error?: any; state?: any };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const StatusIndicator = memo<StatusIndicatorProps>(({ intervention, result }) => {
|
|
15
|
+
const { t } = useTranslation('chat');
|
|
16
|
+
const theme = useTheme();
|
|
17
|
+
|
|
18
|
+
const hasError = !!result?.error;
|
|
19
|
+
const isReject = intervention?.status === 'rejected';
|
|
20
|
+
const isAbort = intervention?.status === 'aborted';
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Flexbox align={'center'} gap={4} horizontal style={{ fontSize: 12 }}>
|
|
24
|
+
{isAbort ? (
|
|
25
|
+
<Tooltip title={t('tool.intervention.toolAbort')}>
|
|
26
|
+
<Icon color={theme.colorTextTertiary} icon={CircleStop} />
|
|
27
|
+
</Tooltip>
|
|
28
|
+
) : isReject ? (
|
|
29
|
+
<Tooltip title={t('tool.intervention.toolRejected')}>
|
|
30
|
+
<Icon color={theme.colorTextTertiary} icon={Ban} />
|
|
31
|
+
</Tooltip>
|
|
32
|
+
) : hasError ? (
|
|
33
|
+
<Icon color={theme.colorError} icon={X} />
|
|
34
|
+
) : (
|
|
35
|
+
<Icon color={theme.colorSuccess} icon={Check} />
|
|
36
|
+
)}
|
|
37
|
+
</Flexbox>
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export default StatusIndicator;
|
|
@@ -26,6 +26,9 @@ export const useStyles = createStyles(({ css, token }) => ({
|
|
|
26
26
|
text-overflow: ellipsis;
|
|
27
27
|
`,
|
|
28
28
|
|
|
29
|
+
expand: css`
|
|
30
|
+
color: ${token.colorText};
|
|
31
|
+
`,
|
|
29
32
|
shinyText: shinyTextStylish(token),
|
|
30
33
|
}));
|
|
31
34
|
|
|
@@ -33,15 +36,16 @@ interface ToolTitleProps {
|
|
|
33
36
|
apiName: string;
|
|
34
37
|
identifier: string;
|
|
35
38
|
index: number;
|
|
39
|
+
isExpanded?: boolean;
|
|
36
40
|
isLoading?: boolean;
|
|
37
41
|
messageId: string;
|
|
38
42
|
toolCallId: string;
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
const ToolTitle = memo<ToolTitleProps>(
|
|
42
|
-
({ identifier, apiName, isLoading, index, toolCallId, messageId }) => {
|
|
46
|
+
({ identifier, apiName, isLoading, index, toolCallId, messageId, isExpanded }) => {
|
|
43
47
|
const { t } = useTranslation('plugin');
|
|
44
|
-
const { styles } = useStyles();
|
|
48
|
+
const { styles, cx } = useStyles();
|
|
45
49
|
|
|
46
50
|
const pluginMeta = useToolStore(toolSelectors.getMetaById(identifier), isEqual);
|
|
47
51
|
|
|
@@ -69,6 +73,7 @@ const ToolTitle = memo<ToolTitleProps>(
|
|
|
69
73
|
{...builtinPluginTitle}
|
|
70
74
|
identifier={identifier}
|
|
71
75
|
index={index}
|
|
76
|
+
isExpanded={isExpanded}
|
|
72
77
|
isLoading={isLoading}
|
|
73
78
|
messageId={messageId}
|
|
74
79
|
toolCallId={toolCallId}
|
|
@@ -79,7 +84,12 @@ const ToolTitle = memo<ToolTitleProps>(
|
|
|
79
84
|
const pluginTitle = pluginHelpers.getPluginTitle(pluginMeta) ?? t('unknownPlugin');
|
|
80
85
|
|
|
81
86
|
return (
|
|
82
|
-
<Flexbox
|
|
87
|
+
<Flexbox
|
|
88
|
+
align={'center'}
|
|
89
|
+
className={cx(isLoading && styles.shinyText, isExpanded && styles.expand)}
|
|
90
|
+
gap={6}
|
|
91
|
+
horizontal
|
|
92
|
+
>
|
|
83
93
|
<div>{pluginTitle}</div> <Icon icon={ChevronRight} />
|
|
84
94
|
<span className={styles.apiName}>{apiName}</span>
|
|
85
95
|
</Flexbox>
|
|
@@ -1,26 +1,19 @@
|
|
|
1
1
|
import { ToolIntervention } from '@lobechat/types';
|
|
2
|
-
import { ActionIcon
|
|
2
|
+
import { ActionIcon } from '@lobehub/ui';
|
|
3
3
|
import { createStyles } from 'antd-style';
|
|
4
|
-
import {
|
|
5
|
-
Ban,
|
|
6
|
-
Check,
|
|
7
|
-
LayoutPanelTop,
|
|
8
|
-
LogsIcon,
|
|
9
|
-
LucideBug,
|
|
10
|
-
LucideBugOff,
|
|
11
|
-
Trash2,
|
|
12
|
-
X,
|
|
13
|
-
} from 'lucide-react';
|
|
4
|
+
import { LayoutPanelTop, LogsIcon, LucideBug, LucideBugOff, Trash2 } from 'lucide-react';
|
|
14
5
|
import { CSSProperties, memo, useEffect, useState } from 'react';
|
|
15
6
|
import { useTranslation } from 'react-i18next';
|
|
16
7
|
import { Flexbox } from 'react-layout-kit';
|
|
17
8
|
|
|
18
9
|
import { LOADING_FLAT } from '@/const/message';
|
|
19
10
|
import { useChatStore } from '@/store/chat';
|
|
11
|
+
import { dbMessageSelectors } from '@/store/chat/slices/message/selectors';
|
|
20
12
|
import { shinyTextStylish } from '@/styles/loading';
|
|
21
13
|
|
|
22
14
|
import Debug from './Debug';
|
|
23
15
|
import Settings from './Settings';
|
|
16
|
+
import StatusIndicator from './StatusIndicator';
|
|
24
17
|
import ToolTitle from './ToolTitle';
|
|
25
18
|
|
|
26
19
|
export const useStyles = createStyles(({ css, token, cx }) => ({
|
|
@@ -86,6 +79,7 @@ interface InspectorProps {
|
|
|
86
79
|
showPortal?: boolean;
|
|
87
80
|
showRender: boolean;
|
|
88
81
|
style?: CSSProperties;
|
|
82
|
+
toolMessageId?: string;
|
|
89
83
|
type?: string;
|
|
90
84
|
}
|
|
91
85
|
|
|
@@ -103,15 +97,18 @@ const Inspectors = memo<InspectorProps>(
|
|
|
103
97
|
setShowPluginRender,
|
|
104
98
|
type,
|
|
105
99
|
intervention,
|
|
100
|
+
toolMessageId,
|
|
106
101
|
}) => {
|
|
107
102
|
const { t } = useTranslation('plugin');
|
|
108
|
-
const { styles
|
|
103
|
+
const { styles } = useStyles();
|
|
109
104
|
|
|
110
105
|
const [showDebug, setShowDebug] = useState(false);
|
|
111
|
-
const [isPinned, setIsPinned] = useState(false);
|
|
112
106
|
const [isHovered, setIsHovered] = useState(false);
|
|
113
107
|
|
|
114
|
-
const [deleteAssistantMessage] = useChatStore((s) => [
|
|
108
|
+
const [deleteAssistantMessage, toggleInspectExpanded] = useChatStore((s) => [
|
|
109
|
+
s.deleteAssistantMessage,
|
|
110
|
+
s.toggleInspectExpanded,
|
|
111
|
+
]);
|
|
115
112
|
|
|
116
113
|
const hasError = !!result?.error;
|
|
117
114
|
const hasSuccessResult = !!result?.content && result.content !== LOADING_FLAT;
|
|
@@ -119,18 +116,26 @@ const Inspectors = memo<InspectorProps>(
|
|
|
119
116
|
const hasResult = hasSuccessResult || hasError;
|
|
120
117
|
|
|
121
118
|
const isPending = intervention?.status === 'pending';
|
|
122
|
-
const isReject = intervention?.status === 'rejected'
|
|
119
|
+
const isReject = intervention?.status === 'rejected';
|
|
120
|
+
const isAbort = intervention?.status === 'aborted';
|
|
123
121
|
const isTitleLoading = !hasResult && !isPending;
|
|
124
122
|
|
|
125
|
-
|
|
126
|
-
|
|
123
|
+
const isPersistentExpanded = useChatStore((s) => {
|
|
124
|
+
if (!toolMessageId) return undefined;
|
|
125
|
+
|
|
126
|
+
const message = dbMessageSelectors.getDbMessageById(toolMessageId)(s);
|
|
127
|
+
return message?.metadata?.inspectExpanded;
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Compute actual render state based on persistent expanded or hovered
|
|
131
|
+
const shouldShowRender = isPersistentExpanded || isHovered;
|
|
127
132
|
|
|
128
133
|
// Sync with parent state
|
|
129
134
|
useEffect(() => {
|
|
130
135
|
setShowRender(shouldShowRender);
|
|
131
136
|
}, [shouldShowRender, setShowRender]);
|
|
132
137
|
|
|
133
|
-
const showCustomPluginRender = shouldShowRender && !isPending && !isReject;
|
|
138
|
+
const showCustomPluginRender = shouldShowRender && !isPending && !isReject && !isAbort;
|
|
134
139
|
return (
|
|
135
140
|
<Flexbox className={styles.container} gap={4}>
|
|
136
141
|
<Flexbox align={'center'} distribution={'space-between'} gap={8} horizontal>
|
|
@@ -140,15 +145,15 @@ const Inspectors = memo<InspectorProps>(
|
|
|
140
145
|
gap={8}
|
|
141
146
|
horizontal
|
|
142
147
|
onClick={() => {
|
|
143
|
-
|
|
148
|
+
if (toolMessageId) toggleInspectExpanded(toolMessageId);
|
|
144
149
|
}}
|
|
145
150
|
onMouseEnter={() => {
|
|
146
|
-
if (!
|
|
151
|
+
if (!isPersistentExpanded) {
|
|
147
152
|
setIsHovered(true);
|
|
148
153
|
}
|
|
149
154
|
}}
|
|
150
155
|
onMouseLeave={() => {
|
|
151
|
-
if (!
|
|
156
|
+
if (!isPersistentExpanded) {
|
|
152
157
|
setIsHovered(false);
|
|
153
158
|
}
|
|
154
159
|
}}
|
|
@@ -158,6 +163,7 @@ const Inspectors = memo<InspectorProps>(
|
|
|
158
163
|
apiName={apiName}
|
|
159
164
|
identifier={identifier}
|
|
160
165
|
index={index}
|
|
166
|
+
isExpanded={isPersistentExpanded}
|
|
161
167
|
isLoading={isTitleLoading}
|
|
162
168
|
messageId={assistantMessageId}
|
|
163
169
|
toolCallId={id}
|
|
@@ -194,19 +200,7 @@ const Inspectors = memo<InspectorProps>(
|
|
|
194
200
|
|
|
195
201
|
<Settings id={identifier} />
|
|
196
202
|
</Flexbox>
|
|
197
|
-
{hasResult &&
|
|
198
|
-
<Flexbox align={'center'} gap={4} horizontal style={{ fontSize: 12 }}>
|
|
199
|
-
{isReject ? (
|
|
200
|
-
<Tooltip title={t('tool.intervention.toolRejected', { ns: 'chat' })}>
|
|
201
|
-
<Icon color={theme.colorTextTertiary} icon={Ban} />
|
|
202
|
-
</Tooltip>
|
|
203
|
-
) : hasError ? (
|
|
204
|
-
<Icon color={theme.colorError} icon={X} />
|
|
205
|
-
) : (
|
|
206
|
-
<Icon color={theme.colorSuccess} icon={Check} />
|
|
207
|
-
)}
|
|
208
|
-
</Flexbox>
|
|
209
|
-
)}
|
|
203
|
+
{hasResult && <StatusIndicator intervention={intervention} result={result} />}
|
|
210
204
|
</Flexbox>
|
|
211
205
|
</Flexbox>
|
|
212
206
|
{showDebug && (
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Icon } from '@lobehub/ui';
|
|
2
|
+
import { createStyles } from 'antd-style';
|
|
3
|
+
import { BanIcon } from 'lucide-react';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import { Flexbox } from 'react-layout-kit';
|
|
7
|
+
|
|
8
|
+
const useStyles = createStyles(({ css, token }) => ({
|
|
9
|
+
container: css`
|
|
10
|
+
padding-block: 8px;
|
|
11
|
+
padding-inline: 6px;
|
|
12
|
+
`,
|
|
13
|
+
reason: css`
|
|
14
|
+
font-size: 12px;
|
|
15
|
+
color: ${token.colorTextTertiary};
|
|
16
|
+
`,
|
|
17
|
+
title: css`
|
|
18
|
+
font-size: 14px;
|
|
19
|
+
color: ${token.colorTextSecondary};
|
|
20
|
+
`,
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
const AbortResponse = memo(() => {
|
|
24
|
+
const { t } = useTranslation('chat');
|
|
25
|
+
const { styles, theme } = useStyles();
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Flexbox className={styles.container} gap={8}>
|
|
29
|
+
<Flexbox align={'center'} gap={8} horizontal>
|
|
30
|
+
<Icon color={theme.colorTextTertiary} icon={BanIcon} size={16} />
|
|
31
|
+
<div className={styles.title}>{t('tool.intervention.toolAbort')}</div>
|
|
32
|
+
</Flexbox>
|
|
33
|
+
</Flexbox>
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export default AbortResponse;
|
|
@@ -3,6 +3,8 @@ import { ChatToolResult, ToolIntervention } from '@lobechat/types';
|
|
|
3
3
|
import { Suspense, memo } from 'react';
|
|
4
4
|
import { Flexbox } from 'react-layout-kit';
|
|
5
5
|
|
|
6
|
+
import AbortResponse from '@/features/Conversation/Messages/Group/Tool/Render/AbortResponse';
|
|
7
|
+
|
|
6
8
|
import CustomRender from './CustomRender';
|
|
7
9
|
import ErrorResponse from './ErrorResponse';
|
|
8
10
|
import Intervention from './Intervention';
|
|
@@ -63,6 +65,10 @@ const Render = memo<RenderProps>(
|
|
|
63
65
|
return <RejectedResponse reason={intervention.rejectedReason} />;
|
|
64
66
|
}
|
|
65
67
|
|
|
68
|
+
if (intervention?.status === 'aborted') {
|
|
69
|
+
return <AbortResponse />;
|
|
70
|
+
}
|
|
71
|
+
|
|
66
72
|
if (!result) return null;
|
|
67
73
|
|
|
68
74
|
// Handle error state
|
|
@@ -70,6 +70,7 @@ const Tool = memo<GroupToolProps>(
|
|
|
70
70
|
setShowRender={setShowToolDetail}
|
|
71
71
|
showPluginRender={showCustomPluginUI}
|
|
72
72
|
showRender={showToolContent}
|
|
73
|
+
toolMessageId={toolMessageId}
|
|
73
74
|
type={type}
|
|
74
75
|
/>
|
|
75
76
|
<AnimatedCollapsed open={showToolContent} width={{ collapsed: 'auto' }}>
|
|
@@ -220,12 +220,6 @@ export const fileRouter = router({
|
|
|
220
220
|
embeddingStatus: null,
|
|
221
221
|
finishEmbedding: false,
|
|
222
222
|
} as FileListItem;
|
|
223
|
-
console.log('[API getKnowledgeItems] Processing document:', {
|
|
224
|
-
editorDataPreview: item.editorData ? JSON.stringify(item.editorData).slice(0, 100) : null,
|
|
225
|
-
hasEditorData: !!item.editorData,
|
|
226
|
-
id: item.id,
|
|
227
|
-
name: item.name,
|
|
228
|
-
});
|
|
229
223
|
resultItems.push(documentItem);
|
|
230
224
|
}
|
|
231
225
|
}
|
|
@@ -47,6 +47,10 @@ export interface MessagePublicApiAction {
|
|
|
47
47
|
* Toggle message collapsed state
|
|
48
48
|
*/
|
|
49
49
|
toggleMessageCollapsed: (id: string, collapsed?: boolean) => Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Toggle tool inspect expanded state
|
|
52
|
+
*/
|
|
53
|
+
toggleInspectExpanded: (id: string, expanded?: boolean) => Promise<void>;
|
|
50
54
|
|
|
51
55
|
// ===== Others ===== //
|
|
52
56
|
copyMessage: (id: string, content: string) => Promise<void>;
|
|
@@ -258,4 +262,15 @@ export const messagePublicApi: StateCreator<
|
|
|
258
262
|
collapsed: nextCollapsed,
|
|
259
263
|
});
|
|
260
264
|
},
|
|
265
|
+
|
|
266
|
+
toggleInspectExpanded: async (id, expanded) => {
|
|
267
|
+
const message = dbMessageSelectors.getDbMessageById(id)(get());
|
|
268
|
+
if (!message) return;
|
|
269
|
+
|
|
270
|
+
// 如果没有传入 expanded,则取反当前状态
|
|
271
|
+
const nextExpanded = expanded ?? !message.metadata?.inspectExpanded;
|
|
272
|
+
|
|
273
|
+
// 直接调用现有的 optimisticUpdateMessageMetadata
|
|
274
|
+
await get().optimisticUpdateMessageMetadata(id, { inspectExpanded: nextExpanded });
|
|
275
|
+
},
|
|
261
276
|
});
|