@lobehub/chat 1.142.2 → 1.142.4
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 +52 -0
- package/README.md +8 -8
- package/README.zh-CN.md +8 -8
- package/changelog/v1.json +18 -0
- package/docs/development/database-schema.dbml +1 -0
- package/locales/ar/chat.json +4 -4
- package/locales/ar/file.json +1 -0
- package/locales/ar/models.json +1 -1
- package/locales/bg-BG/chat.json +4 -4
- package/locales/bg-BG/file.json +1 -0
- package/locales/bg-BG/models.json +1 -1
- package/locales/de-DE/chat.json +4 -4
- package/locales/de-DE/file.json +1 -0
- package/locales/de-DE/models.json +1 -1
- package/locales/en-US/chat.json +4 -4
- package/locales/en-US/file.json +1 -0
- package/locales/en-US/models.json +1 -1
- package/locales/es-ES/chat.json +4 -4
- package/locales/es-ES/file.json +1 -0
- package/locales/es-ES/models.json +1 -1
- package/locales/fa-IR/chat.json +4 -4
- package/locales/fa-IR/file.json +1 -0
- package/locales/fa-IR/models.json +1 -1
- package/locales/fr-FR/chat.json +4 -4
- package/locales/fr-FR/file.json +1 -0
- package/locales/fr-FR/models.json +1 -1
- package/locales/it-IT/chat.json +4 -4
- package/locales/it-IT/file.json +1 -0
- package/locales/ja-JP/chat.json +4 -4
- package/locales/ja-JP/file.json +1 -0
- package/locales/ja-JP/models.json +1 -1
- package/locales/ko-KR/chat.json +4 -4
- package/locales/ko-KR/file.json +1 -0
- package/locales/ko-KR/models.json +1 -1
- package/locales/nl-NL/chat.json +4 -4
- package/locales/nl-NL/file.json +1 -0
- package/locales/nl-NL/models.json +1 -1
- package/locales/pl-PL/chat.json +4 -4
- package/locales/pl-PL/file.json +1 -0
- package/locales/pl-PL/models.json +1 -1
- package/locales/pt-BR/chat.json +4 -4
- package/locales/pt-BR/file.json +1 -0
- package/locales/ru-RU/chat.json +4 -4
- package/locales/ru-RU/file.json +1 -0
- package/locales/ru-RU/models.json +1 -1
- package/locales/tr-TR/chat.json +4 -4
- package/locales/tr-TR/file.json +1 -0
- package/locales/tr-TR/models.json +1 -1
- package/locales/vi-VN/chat.json +4 -4
- package/locales/vi-VN/file.json +1 -0
- package/locales/vi-VN/models.json +1 -1
- package/locales/zh-CN/chat.json +4 -4
- package/locales/zh-CN/file.json +1 -0
- package/locales/zh-TW/chat.json +4 -4
- package/locales/zh-TW/file.json +1 -0
- package/locales/zh-TW/models.json +1 -1
- package/package.json +3 -2
- package/packages/const/src/file.ts +2 -0
- package/packages/database/migrations/0039_add_editor_data.sql +1 -0
- package/packages/database/migrations/meta/0039_snapshot.json +7586 -0
- package/packages/database/migrations/meta/_journal.json +7 -0
- package/packages/database/src/core/migrations.json +6 -0
- package/packages/database/src/schemas/document.ts +2 -0
- package/packages/database/src/utils/__tests__/groupMessages.test.ts +989 -0
- package/packages/database/src/utils/groupMessages.ts +359 -0
- package/packages/memory-extract/.env.example +3 -0
- package/packages/memory-extract/package.json +21 -0
- package/packages/memory-extract/vitest.config.mts +10 -0
- package/packages/model-runtime/src/core/streams/protocol.ts +3 -3
- package/packages/model-runtime/src/types/chat.ts +2 -2
- package/packages/obervability-otel/package.json +7 -7
- package/packages/types/src/message/common/base.ts +0 -1
- package/packages/types/src/message/common/metadata.ts +5 -5
- package/packages/types/src/message/common/tools.ts +17 -0
- package/packages/types/src/message/db/item.ts +23 -17
- package/packages/types/src/message/ui/chat.ts +22 -66
- package/packages/types/src/message/ui/index.ts +1 -0
- package/packages/types/src/message/ui/params.ts +65 -0
- package/packages/types/src/tool/builtin.ts +34 -0
- package/packages/types/src/tool/intervention.ts +39 -0
- package/packages/utils/src/fetch/fetchSSE.ts +4 -4
- package/renovate.json +14 -2
- package/src/app/[variants]/(main)/settings/provider/features/ModelList/CreateNewModelModal/index.tsx +7 -0
- package/src/app/[variants]/(main)/settings/provider/features/ModelList/ModelConfigModal/index.tsx +7 -0
- package/src/app/[variants]/(main)/settings/provider/features/ProviderConfig/Checker.tsx +7 -2
- package/src/features/ChatInput/ActionBar/components/ActionDropdown.tsx +21 -1
- package/src/features/ChatItem/components/Title.tsx +4 -3
- package/src/features/Conversation/Messages/Assistant/MessageContent.tsx +3 -16
- package/src/features/Conversation/Messages/Assistant/index.tsx +3 -3
- package/src/features/Conversation/{utils.test.ts → utils/markdown.test.ts} +1 -1
- package/src/features/Conversation/{utils.ts → utils/markdown.ts} +1 -1
- package/src/features/FileManager/FileList/FileListItem/index.tsx +3 -2
- package/src/features/FileManager/FileList/MasonryFileItem/MasonryItemWrapper.tsx +1 -1
- package/src/features/FileManager/FileList/MasonryFileItem/index.tsx +2 -4
- package/src/features/FileManager/FileList/MasonrySkeleton.tsx +11 -5
- package/src/features/FileManager/FileList/ToolBar/MultiSelectActions.tsx +1 -1
- package/src/features/FileManager/FileList/index.tsx +51 -9
- package/src/features/ModelSwitchPanel/index.tsx +1 -0
- package/src/locales/default/chat.ts +4 -4
- package/src/locales/default/file.ts +1 -0
- package/src/store/file/slices/fileManager/action.test.ts +136 -1
- package/src/store/file/slices/fileManager/action.ts +30 -8
- package/src/tools/web-browsing/Render/PageContent/index.tsx +2 -2
- package/src/tools/web-browsing/Render/index.tsx +5 -4
- package/src/utils/unzipFile.test.ts +128 -0
- package/src/utils/unzipFile.ts +122 -0
- package/vitest.config.mts +1 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { UploadFileItem } from '../../files';
|
|
2
|
+
import { MessageSemanticSearchChunk } from '../../rag';
|
|
3
|
+
import { ChatMessageError } from '../common/base';
|
|
4
|
+
import { UIChatMessage, UIMessageRoleType } from './chat';
|
|
5
|
+
|
|
6
|
+
export interface CreateMessageParams
|
|
7
|
+
extends Partial<Omit<UIChatMessage, 'content' | 'role' | 'topicId' | 'chunksList'>> {
|
|
8
|
+
content: string;
|
|
9
|
+
error?: ChatMessageError | null;
|
|
10
|
+
fileChunks?: MessageSemanticSearchChunk[];
|
|
11
|
+
files?: string[];
|
|
12
|
+
fromModel?: string;
|
|
13
|
+
fromProvider?: string;
|
|
14
|
+
groupId?: string;
|
|
15
|
+
role: UIMessageRoleType;
|
|
16
|
+
sessionId: string;
|
|
17
|
+
targetId?: string | null;
|
|
18
|
+
threadId?: string | null;
|
|
19
|
+
topicId?: string;
|
|
20
|
+
traceId?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface SendMessageParams {
|
|
24
|
+
/**
|
|
25
|
+
* create a thread
|
|
26
|
+
*/
|
|
27
|
+
createThread?: boolean;
|
|
28
|
+
files?: UploadFileItem[];
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* https://github.com/lobehub/lobe-chat/pull/2086
|
|
32
|
+
*/
|
|
33
|
+
isWelcomeQuestion?: boolean;
|
|
34
|
+
message: string;
|
|
35
|
+
/**
|
|
36
|
+
* Additional metadata for the message (e.g., mentioned users)
|
|
37
|
+
*/
|
|
38
|
+
metadata?: Record<string, any>;
|
|
39
|
+
onlyAddUserMessage?: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface SendThreadMessageParams {
|
|
43
|
+
/**
|
|
44
|
+
* create a thread
|
|
45
|
+
*/
|
|
46
|
+
createNewThread?: boolean;
|
|
47
|
+
// files?: UploadFileItem[];
|
|
48
|
+
message: string;
|
|
49
|
+
onlyAddUserMessage?: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface SendGroupMessageParams {
|
|
53
|
+
files?: UploadFileItem[];
|
|
54
|
+
groupId: string;
|
|
55
|
+
message: string;
|
|
56
|
+
/**
|
|
57
|
+
* Additional metadata for the message (e.g., mentioned users)
|
|
58
|
+
*/
|
|
59
|
+
metadata?: Record<string, any>;
|
|
60
|
+
onlyAddUserMessage?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* for group chat
|
|
63
|
+
*/
|
|
64
|
+
targetMemberId?: string | null;
|
|
65
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
+
import { z } from 'zod';
|
|
2
3
|
|
|
4
|
+
import { HumanInterventionConfigSchema, HumanInterventionPolicySchema } from './intervention';
|
|
3
5
|
import type { HumanInterventionConfig, HumanInterventionPolicy } from './intervention';
|
|
4
6
|
|
|
5
7
|
interface Meta {
|
|
@@ -26,6 +28,14 @@ interface Meta {
|
|
|
26
28
|
tags?: string[];
|
|
27
29
|
title: string;
|
|
28
30
|
}
|
|
31
|
+
|
|
32
|
+
const MetaSchema = z.object({
|
|
33
|
+
avatar: z.string().optional(),
|
|
34
|
+
description: z.string().optional(),
|
|
35
|
+
tags: z.array(z.string()).optional(),
|
|
36
|
+
title: z.string(),
|
|
37
|
+
});
|
|
38
|
+
|
|
29
39
|
export interface LobeChatPluginApi {
|
|
30
40
|
description: string;
|
|
31
41
|
/**
|
|
@@ -46,6 +56,14 @@ export interface LobeChatPluginApi {
|
|
|
46
56
|
url?: string;
|
|
47
57
|
}
|
|
48
58
|
|
|
59
|
+
export const LobeChatPluginApiSchema = z.object({
|
|
60
|
+
description: z.string(),
|
|
61
|
+
humanIntervention: HumanInterventionConfigSchema.optional(),
|
|
62
|
+
name: z.string(),
|
|
63
|
+
parameters: z.record(z.string(), z.any()),
|
|
64
|
+
url: z.string().optional(),
|
|
65
|
+
});
|
|
66
|
+
|
|
49
67
|
export interface BuiltinToolManifest {
|
|
50
68
|
api: LobeChatPluginApi[];
|
|
51
69
|
|
|
@@ -74,6 +92,15 @@ export interface BuiltinToolManifest {
|
|
|
74
92
|
type?: 'builtin';
|
|
75
93
|
}
|
|
76
94
|
|
|
95
|
+
export const BuiltinToolManifestSchema = z.object({
|
|
96
|
+
api: z.array(LobeChatPluginApiSchema),
|
|
97
|
+
humanIntervention: HumanInterventionPolicySchema.optional(),
|
|
98
|
+
identifier: z.string(),
|
|
99
|
+
meta: MetaSchema,
|
|
100
|
+
systemRole: z.string(),
|
|
101
|
+
type: z.literal('builtin').optional(),
|
|
102
|
+
});
|
|
103
|
+
|
|
77
104
|
export interface LobeBuiltinTool {
|
|
78
105
|
hidden?: boolean;
|
|
79
106
|
identifier: string;
|
|
@@ -81,6 +108,13 @@ export interface LobeBuiltinTool {
|
|
|
81
108
|
type: 'builtin';
|
|
82
109
|
}
|
|
83
110
|
|
|
111
|
+
export const LobeBuiltinToolSchema = z.object({
|
|
112
|
+
hidden: z.boolean().optional(),
|
|
113
|
+
identifier: z.string(),
|
|
114
|
+
manifest: BuiltinToolManifestSchema,
|
|
115
|
+
type: z.literal('builtin'),
|
|
116
|
+
});
|
|
117
|
+
|
|
84
118
|
export interface BuiltinRenderProps<Content = any, Arguments = any, State = any> {
|
|
85
119
|
apiName?: string;
|
|
86
120
|
args: Arguments;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Human Intervention Policy
|
|
3
5
|
*/
|
|
@@ -6,6 +8,8 @@ export type HumanInterventionPolicy =
|
|
|
6
8
|
| 'always' // Always require intervention
|
|
7
9
|
| 'first'; // Require intervention on first call only
|
|
8
10
|
|
|
11
|
+
export const HumanInterventionPolicySchema = z.enum(['never', 'always', 'first']);
|
|
12
|
+
|
|
9
13
|
/**
|
|
10
14
|
* Argument Matcher for parameter-level filtering
|
|
11
15
|
* Supports wildcard patterns, prefix matching, and regex
|
|
@@ -22,6 +26,14 @@ export type ArgumentMatcher =
|
|
|
22
26
|
type: 'exact' | 'prefix' | 'wildcard' | 'regex';
|
|
23
27
|
};
|
|
24
28
|
|
|
29
|
+
export const ArgumentMatcherSchema: z.ZodType<ArgumentMatcher> = z.union([
|
|
30
|
+
z.string(),
|
|
31
|
+
z.object({
|
|
32
|
+
pattern: z.string(),
|
|
33
|
+
type: z.enum(['exact', 'prefix', 'wildcard', 'regex']),
|
|
34
|
+
}),
|
|
35
|
+
]);
|
|
36
|
+
|
|
25
37
|
/**
|
|
26
38
|
* Human Intervention Rule
|
|
27
39
|
* Used for parameter-level control of intervention behavior
|
|
@@ -42,6 +54,11 @@ export interface HumanInterventionRule {
|
|
|
42
54
|
policy: HumanInterventionPolicy;
|
|
43
55
|
}
|
|
44
56
|
|
|
57
|
+
export const HumanInterventionRuleSchema: z.ZodType<HumanInterventionRule> = z.object({
|
|
58
|
+
match: z.record(z.string(), ArgumentMatcherSchema).optional(),
|
|
59
|
+
policy: HumanInterventionPolicySchema,
|
|
60
|
+
});
|
|
61
|
+
|
|
45
62
|
/**
|
|
46
63
|
* Human Intervention Configuration
|
|
47
64
|
* Can be either:
|
|
@@ -54,6 +71,11 @@ export interface HumanInterventionRule {
|
|
|
54
71
|
*/
|
|
55
72
|
export type HumanInterventionConfig = HumanInterventionPolicy | HumanInterventionRule[];
|
|
56
73
|
|
|
74
|
+
export const HumanInterventionConfigSchema: z.ZodType<HumanInterventionConfig> = z.union([
|
|
75
|
+
HumanInterventionPolicySchema,
|
|
76
|
+
z.array(HumanInterventionRuleSchema),
|
|
77
|
+
]);
|
|
78
|
+
|
|
57
79
|
/**
|
|
58
80
|
* Human Intervention Response
|
|
59
81
|
* User's response to an intervention request
|
|
@@ -85,6 +107,16 @@ export interface HumanInterventionResponse {
|
|
|
85
107
|
};
|
|
86
108
|
}
|
|
87
109
|
|
|
110
|
+
export const HumanInterventionResponseSchema = z.object({
|
|
111
|
+
action: z.enum(['approve', 'reject', 'select']),
|
|
112
|
+
data: z
|
|
113
|
+
.object({
|
|
114
|
+
remember: z.boolean().optional(),
|
|
115
|
+
selected: z.union([z.string(), z.array(z.string())]).optional(),
|
|
116
|
+
})
|
|
117
|
+
.optional(),
|
|
118
|
+
});
|
|
119
|
+
|
|
88
120
|
/**
|
|
89
121
|
* Parameters for shouldIntervene method
|
|
90
122
|
*/
|
|
@@ -112,3 +144,10 @@ export interface ShouldInterveneParams {
|
|
|
112
144
|
*/
|
|
113
145
|
toolKey?: string;
|
|
114
146
|
}
|
|
147
|
+
|
|
148
|
+
export const ShouldInterveneParamsSchema = z.object({
|
|
149
|
+
config: HumanInterventionConfigSchema.optional(),
|
|
150
|
+
confirmedHistory: z.array(z.string()).optional(),
|
|
151
|
+
toolArgs: z.record(z.string(), z.any()).optional(),
|
|
152
|
+
toolKey: z.string().optional(),
|
|
153
|
+
});
|
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
ChatMessageError,
|
|
7
7
|
GroundingSearch,
|
|
8
8
|
MessageToolCall,
|
|
9
|
+
ModelPerformance,
|
|
9
10
|
ModelReasoning,
|
|
10
|
-
ModelSpeed,
|
|
11
11
|
ModelUsage,
|
|
12
12
|
ResponseAnimation,
|
|
13
13
|
ResponseAnimationStyle,
|
|
@@ -26,7 +26,7 @@ export type OnFinishHandler = (
|
|
|
26
26
|
images?: ChatImageChunk[];
|
|
27
27
|
observationId?: string | null;
|
|
28
28
|
reasoning?: ModelReasoning;
|
|
29
|
-
speed?:
|
|
29
|
+
speed?: ModelPerformance;
|
|
30
30
|
toolCalls?: MessageToolCall[];
|
|
31
31
|
traceId?: string | null;
|
|
32
32
|
type?: SSEFinishType;
|
|
@@ -40,7 +40,7 @@ export interface MessageUsageChunk {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export interface MessageSpeedChunk {
|
|
43
|
-
speed:
|
|
43
|
+
speed: ModelPerformance;
|
|
44
44
|
type: 'speed';
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -265,7 +265,7 @@ export const fetchSSE = async (url: string, options: RequestInit & FetchSSEOptio
|
|
|
265
265
|
let grounding: GroundingSearch | undefined = undefined;
|
|
266
266
|
let usage: ModelUsage | undefined = undefined;
|
|
267
267
|
let images: ChatImageChunk[] = [];
|
|
268
|
-
let speed:
|
|
268
|
+
let speed: ModelPerformance | undefined = undefined;
|
|
269
269
|
|
|
270
270
|
await fetchEventSource(url, {
|
|
271
271
|
body: options.body,
|
package/renovate.json
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
3
|
-
"
|
|
4
|
-
|
|
3
|
+
"extends": [
|
|
4
|
+
"config:recommended",
|
|
5
|
+
":dependencyDashboard",
|
|
6
|
+
"schedule:weekly",
|
|
7
|
+
":prHourlyLimitNone",
|
|
8
|
+
":prConcurrentLimitNone",
|
|
9
|
+
":semanticPrefixFixDepsChoreOthers",
|
|
10
|
+
"group:monorepos",
|
|
11
|
+
"group:recommended",
|
|
12
|
+
"group:allNonMajor",
|
|
13
|
+
"replacements:all",
|
|
14
|
+
"workarounds:all"
|
|
15
|
+
],
|
|
5
16
|
"ignoreDeps": [],
|
|
6
17
|
"labels": ["dependencies"],
|
|
7
18
|
"postUpdateOptions": ["yarnDedupeHighest"],
|
|
8
19
|
"prConcurrentLimit": 30,
|
|
9
20
|
"prHourlyLimit": 0,
|
|
21
|
+
"rangeStrategy": "bump",
|
|
10
22
|
"rebaseWhen": "conflicted",
|
|
11
23
|
"schedule": "on sunday before 6:00am",
|
|
12
24
|
"timezone": "UTC"
|
package/src/app/[variants]/(main)/settings/provider/features/ModelList/CreateNewModelModal/index.tsx
CHANGED
|
@@ -64,6 +64,13 @@ const ModelConfigModal = memo<ModelConfigModalProps>(({ open, setOpen }) => {
|
|
|
64
64
|
maskClosable
|
|
65
65
|
onCancel={closeModal}
|
|
66
66
|
open={open}
|
|
67
|
+
styles={{
|
|
68
|
+
content: {
|
|
69
|
+
display: 'flex',
|
|
70
|
+
flexDirection: 'column',
|
|
71
|
+
maxHeight: 'calc(100vh - 150px)',
|
|
72
|
+
},
|
|
73
|
+
}}
|
|
67
74
|
title={t('providerModels.createNew.title')}
|
|
68
75
|
zIndex={1251} // Select is 1150
|
|
69
76
|
>
|
package/src/app/[variants]/(main)/settings/provider/features/ModelList/ModelConfigModal/index.tsx
CHANGED
|
@@ -59,6 +59,13 @@ const ModelConfigModal = memo<ModelConfigModalProps>(({ id, open, setOpen }) =>
|
|
|
59
59
|
maskClosable
|
|
60
60
|
onCancel={closeModal}
|
|
61
61
|
open={open}
|
|
62
|
+
styles={{
|
|
63
|
+
content: {
|
|
64
|
+
display: 'flex',
|
|
65
|
+
flexDirection: 'column',
|
|
66
|
+
maxHeight: 'calc(100vh - 150px)',
|
|
67
|
+
},
|
|
68
|
+
}}
|
|
62
69
|
title={t('llm.customModelCards.modelConfig.modalTitle', { ns: 'setting' })}
|
|
63
70
|
zIndex={1251} // Select is 1150
|
|
64
71
|
>
|
|
@@ -19,11 +19,16 @@ const Error = memo<{ error: ChatMessageError }>(({ error }) => {
|
|
|
19
19
|
const providerName = useProviderName(error.body?.provider);
|
|
20
20
|
|
|
21
21
|
return (
|
|
22
|
-
<Flexbox gap={8} style={{ width: '100%' }}>
|
|
22
|
+
<Flexbox gap={8} style={{ maxWidth: 600, width: '100%' }}>
|
|
23
23
|
<Alert
|
|
24
24
|
extra={
|
|
25
25
|
<Flexbox>
|
|
26
|
-
<Highlighter
|
|
26
|
+
<Highlighter
|
|
27
|
+
actionIconSize={'small'}
|
|
28
|
+
language={'json'}
|
|
29
|
+
variant={'borderless'}
|
|
30
|
+
wrap={true}
|
|
31
|
+
>
|
|
27
32
|
{JSON.stringify(error.body || error, null, 2)}
|
|
28
33
|
</Highlighter>
|
|
29
34
|
</Flexbox>
|
|
@@ -23,16 +23,36 @@ export interface ActionDropdownProps extends DropdownProps {
|
|
|
23
23
|
maxHeight?: number | string;
|
|
24
24
|
maxWidth?: number | string;
|
|
25
25
|
minWidth?: number | string;
|
|
26
|
+
/**
|
|
27
|
+
* 是否在挂载时预渲染弹层,避免首次触发展开时的渲染卡顿
|
|
28
|
+
*/
|
|
29
|
+
prefetch?: boolean;
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
const ActionDropdown = memo<ActionDropdownProps>(
|
|
29
|
-
({
|
|
33
|
+
({
|
|
34
|
+
menu,
|
|
35
|
+
maxHeight,
|
|
36
|
+
minWidth,
|
|
37
|
+
maxWidth,
|
|
38
|
+
children,
|
|
39
|
+
placement = 'top',
|
|
40
|
+
prefetch = false,
|
|
41
|
+
destroyOnHidden,
|
|
42
|
+
forceRender,
|
|
43
|
+
...rest
|
|
44
|
+
}) => {
|
|
30
45
|
const { cx, styles } = useStyles();
|
|
31
46
|
const isMobile = useIsMobile();
|
|
32
47
|
|
|
48
|
+
const dropdownForceRender = prefetch ? true : forceRender;
|
|
49
|
+
const dropdownDestroyOnHidden = prefetch ? false : destroyOnHidden;
|
|
50
|
+
|
|
33
51
|
return (
|
|
34
52
|
<Dropdown
|
|
35
53
|
arrow={false}
|
|
54
|
+
destroyOnHidden={dropdownDestroyOnHidden}
|
|
55
|
+
forceRender={dropdownForceRender}
|
|
36
56
|
menu={{
|
|
37
57
|
...menu,
|
|
38
58
|
className: cx(styles.dropdownMenu, menu.className),
|
|
@@ -7,6 +7,7 @@ import { ChatItemProps } from '../type';
|
|
|
7
7
|
|
|
8
8
|
export interface TitleProps {
|
|
9
9
|
avatar: ChatItemProps['avatar'];
|
|
10
|
+
className?: string;
|
|
10
11
|
placement?: ChatItemProps['placement'];
|
|
11
12
|
showTitle?: ChatItemProps['showTitle'];
|
|
12
13
|
time?: ChatItemProps['time'];
|
|
@@ -26,13 +27,13 @@ const formatTime = (time: number): string => {
|
|
|
26
27
|
}
|
|
27
28
|
};
|
|
28
29
|
|
|
29
|
-
const Title = memo<TitleProps>(({ showTitle, placement, time, avatar, titleAddon }) => {
|
|
30
|
-
const { styles } = useStyles({ placement, showTitle, time });
|
|
30
|
+
const Title = memo<TitleProps>(({ showTitle, placement, time, avatar, titleAddon, className }) => {
|
|
31
|
+
const { styles, cx } = useStyles({ placement, showTitle, time });
|
|
31
32
|
|
|
32
33
|
return (
|
|
33
34
|
<Flexbox
|
|
34
35
|
align={'center'}
|
|
35
|
-
className={styles.name}
|
|
36
|
+
className={cx(styles.name, className)}
|
|
36
37
|
direction={placement === 'left' ? 'horizontal' : 'horizontal-reverse'}
|
|
37
38
|
gap={4}
|
|
38
39
|
>
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
+
import { LOADING_FLAT } from '@lobechat/const';
|
|
1
2
|
import { UIChatMessage } from '@lobechat/types';
|
|
2
3
|
import { ReactNode, memo } from 'react';
|
|
3
4
|
import { Flexbox } from 'react-layout-kit';
|
|
4
5
|
|
|
5
|
-
import { LOADING_FLAT } from '@/const/message';
|
|
6
|
-
import { AssistantBlock } from '@/features/Conversation/Messages/Assistant/Block';
|
|
7
|
-
import ImageFileListViewer from '@/features/Conversation/Messages/User/ImageFileListViewer';
|
|
8
|
-
import VideoFileListViewer from '@/features/Conversation/Messages/User/VideoFileListViewer';
|
|
9
6
|
import { useChatStore } from '@/store/chat';
|
|
10
7
|
import { aiChatSelectors, chatSelectors } from '@/store/chat/selectors';
|
|
11
8
|
|
|
12
9
|
import { DefaultMessage } from '../Default';
|
|
10
|
+
import ImageFileListViewer from '../User/ImageFileListViewer';
|
|
13
11
|
import FileChunks from './FileChunks';
|
|
14
12
|
import IntentUnderstanding from './IntentUnderstanding';
|
|
15
13
|
import Reasoning from './Reasoning';
|
|
@@ -20,7 +18,7 @@ export const AssistantMessageContent = memo<
|
|
|
20
18
|
UIChatMessage & {
|
|
21
19
|
editableContent: ReactNode;
|
|
22
20
|
}
|
|
23
|
-
>(({ id, tools, content, chunksList, search, imageList,
|
|
21
|
+
>(({ id, tools, content, chunksList, search, imageList, ...props }) => {
|
|
24
22
|
const editing = useChatStore(chatSelectors.isMessageEditing(id));
|
|
25
23
|
const generating = useChatStore(chatSelectors.isMessageGenerating(id));
|
|
26
24
|
|
|
@@ -32,7 +30,6 @@ export const AssistantMessageContent = memo<
|
|
|
32
30
|
|
|
33
31
|
const showSearch = !!search && !!search.citations?.length;
|
|
34
32
|
const showImageItems = !!imageList && imageList.length > 0;
|
|
35
|
-
const showVideoItems = !!videoList && videoList.length > 0;
|
|
36
33
|
|
|
37
34
|
// remove \n to avoid empty content
|
|
38
35
|
// refs: https://github.com/lobehub/lobe-chat/pull/6153
|
|
@@ -42,15 +39,6 @@ export const AssistantMessageContent = memo<
|
|
|
42
39
|
|
|
43
40
|
const showFileChunks = !!chunksList && chunksList.length > 0;
|
|
44
41
|
|
|
45
|
-
if (children && children?.length > 0)
|
|
46
|
-
return (
|
|
47
|
-
<Flexbox gap={8}>
|
|
48
|
-
{children.map((item) => (
|
|
49
|
-
<AssistantBlock key={item.id} {...item} editableContent={props.editableContent} />
|
|
50
|
-
))}
|
|
51
|
-
</Flexbox>
|
|
52
|
-
);
|
|
53
|
-
|
|
54
42
|
return editing ? (
|
|
55
43
|
<DefaultMessage
|
|
56
44
|
content={content}
|
|
@@ -79,7 +67,6 @@ export const AssistantMessageContent = memo<
|
|
|
79
67
|
)
|
|
80
68
|
)}
|
|
81
69
|
{showImageItems && <ImageFileListViewer items={imageList} />}
|
|
82
|
-
{showVideoItems && <VideoFileListViewer items={videoList} />}
|
|
83
70
|
{tools && (
|
|
84
71
|
<Flexbox gap={8}>
|
|
85
72
|
{tools.map((toolCall, index) => (
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { LOADING_FLAT } from '@lobechat/const';
|
|
3
4
|
import { UIChatMessage } from '@lobechat/types';
|
|
4
5
|
import { Tag } from '@lobehub/ui';
|
|
5
6
|
import { useResponsive } from 'antd-style';
|
|
@@ -8,7 +9,6 @@ import { useTranslation } from 'react-i18next';
|
|
|
8
9
|
import { Flexbox } from 'react-layout-kit';
|
|
9
10
|
|
|
10
11
|
import { HtmlPreviewAction } from '@/components/HtmlPreview';
|
|
11
|
-
import { LOADING_FLAT } from '@/const/message';
|
|
12
12
|
import Avatar from '@/features/ChatItem/components/Avatar';
|
|
13
13
|
import BorderSpacing from '@/features/ChatItem/components/BorderSpacing';
|
|
14
14
|
import ErrorContent from '@/features/ChatItem/components/ErrorContent';
|
|
@@ -17,7 +17,7 @@ import Title from '@/features/ChatItem/components/Title';
|
|
|
17
17
|
import { useStyles } from '@/features/ChatItem/style';
|
|
18
18
|
import { useOpenChatSettings } from '@/hooks/useInterceptingRoutes';
|
|
19
19
|
import { useAgentStore } from '@/store/agent';
|
|
20
|
-
import { agentChatConfigSelectors } from '@/store/agent/
|
|
20
|
+
import { agentChatConfigSelectors } from '@/store/agent/selectors';
|
|
21
21
|
import { useChatStore } from '@/store/chat';
|
|
22
22
|
import { chatSelectors } from '@/store/chat/selectors';
|
|
23
23
|
import { chatGroupSelectors, useChatGroupStore } from '@/store/chatGroup';
|
|
@@ -30,7 +30,7 @@ import { userGeneralSettingsSelectors, userProfileSelectors } from '@/store/user
|
|
|
30
30
|
import ErrorMessageExtra, { useErrorContent } from '../../Error';
|
|
31
31
|
import { markdownElements } from '../../MarkdownElements';
|
|
32
32
|
import { useDoubleClickEdit } from '../../hooks/useDoubleClickEdit';
|
|
33
|
-
import { normalizeThinkTags, processWithArtifact } from '../../utils';
|
|
33
|
+
import { normalizeThinkTags, processWithArtifact } from '../../utils/markdown';
|
|
34
34
|
import { AssistantActionsBar } from './Actions';
|
|
35
35
|
import { AssistantMessageExtra } from './Extra';
|
|
36
36
|
import { AssistantMessageContent } from './MessageContent';
|
|
@@ -79,7 +79,7 @@ const useStyles = createStyles(({ css, token, cx, isDarkMode }) => {
|
|
|
79
79
|
interface FileRenderItemProps extends FileListItem {
|
|
80
80
|
index: number;
|
|
81
81
|
knowledgeBaseId?: string;
|
|
82
|
-
onSelectedChange: (id: string, selected: boolean) => void;
|
|
82
|
+
onSelectedChange: (id: string, selected: boolean, shiftKey: boolean, index: number) => void;
|
|
83
83
|
selected?: boolean;
|
|
84
84
|
}
|
|
85
85
|
|
|
@@ -100,6 +100,7 @@ const FileRenderItem = memo<FileRenderItemProps>(
|
|
|
100
100
|
chunkingStatus,
|
|
101
101
|
onSelectedChange,
|
|
102
102
|
knowledgeBaseId,
|
|
103
|
+
index,
|
|
103
104
|
}) => {
|
|
104
105
|
const { t } = useTranslation('components');
|
|
105
106
|
const { styles, cx } = useStyles();
|
|
@@ -140,7 +141,7 @@ const FileRenderItem = memo<FileRenderItemProps>(
|
|
|
140
141
|
onClick={(e) => {
|
|
141
142
|
e.stopPropagation();
|
|
142
143
|
|
|
143
|
-
onSelectedChange(id, !selected);
|
|
144
|
+
onSelectedChange(id, !selected, e.shiftKey, index);
|
|
144
145
|
}}
|
|
145
146
|
style={{ paddingInline: 4 }}
|
|
146
147
|
>
|
|
@@ -21,7 +21,7 @@ const MasonryItemWrapper = memo<MasonryItemWrapperProps>(({ data: item, context
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
return (
|
|
24
|
-
<div style={{ padding: '8px' }}>
|
|
24
|
+
<div style={{ padding: '8px 4px' }}>
|
|
25
25
|
<MasonryFileItem
|
|
26
26
|
knowledgeBaseId={context.knowledgeBaseId}
|
|
27
27
|
onSelectedChange={(id, checked) => {
|
|
@@ -111,8 +111,6 @@ const useStyles = createStyles(({ css, token }) => ({
|
|
|
111
111
|
inset-block-end: 8px;
|
|
112
112
|
inset-inline-end: 8px;
|
|
113
113
|
|
|
114
|
-
padding-block: 4px;
|
|
115
|
-
padding-inline: 8px;
|
|
116
114
|
border-radius: ${token.borderRadius}px;
|
|
117
115
|
|
|
118
116
|
opacity: 0;
|
|
@@ -320,8 +318,8 @@ const MasonryFileItem = memo<MasonryFileItemProps>(
|
|
|
320
318
|
});
|
|
321
319
|
},
|
|
322
320
|
{
|
|
323
|
-
rootMargin: '
|
|
324
|
-
threshold: 0.
|
|
321
|
+
rootMargin: '200px', // Increased margin to load content earlier
|
|
322
|
+
threshold: 0.01, // Lower threshold for earlier triggering
|
|
325
323
|
},
|
|
326
324
|
);
|
|
327
325
|
|
|
@@ -26,6 +26,9 @@ const MasonrySkeleton = memo<MasonrySkeletonProps>(({ columnCount }) => {
|
|
|
26
26
|
// Generate varying heights for more natural masonry look
|
|
27
27
|
const heights = [180, 220, 200, 190, 240, 210, 200, 230, 180, 220, 210, 190];
|
|
28
28
|
|
|
29
|
+
// Calculate number of items based on viewport and column count
|
|
30
|
+
const itemCount = Math.min(columnCount * 3, 12);
|
|
31
|
+
|
|
29
32
|
return (
|
|
30
33
|
<div
|
|
31
34
|
className={styles.grid}
|
|
@@ -33,18 +36,21 @@ const MasonrySkeleton = memo<MasonrySkeletonProps>(({ columnCount }) => {
|
|
|
33
36
|
gridTemplateColumns: `repeat(${columnCount}, 1fr)`,
|
|
34
37
|
}}
|
|
35
38
|
>
|
|
36
|
-
{Array.from({ length:
|
|
39
|
+
{Array.from({ length: itemCount }).map((_, index) => (
|
|
37
40
|
<div className={styles.card} key={index}>
|
|
38
41
|
<Skeleton
|
|
39
42
|
active
|
|
43
|
+
avatar={false}
|
|
40
44
|
paragraph={{
|
|
41
|
-
rows:
|
|
42
|
-
width: ['100%', '
|
|
45
|
+
rows: 4,
|
|
46
|
+
width: ['100%', '90%', '70%', '50%'],
|
|
43
47
|
}}
|
|
44
48
|
style={{
|
|
45
|
-
height: heights[index],
|
|
49
|
+
height: heights[index % heights.length],
|
|
50
|
+
}}
|
|
51
|
+
title={{
|
|
52
|
+
width: '100%',
|
|
46
53
|
}}
|
|
47
|
-
title={false}
|
|
48
54
|
/>
|
|
49
55
|
</div>
|
|
50
56
|
))}
|