@fe-free/ai 4.1.10 → 4.1.12
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 +18 -0
- package/package.json +5 -4
- package/src/ai.stories.tsx +95 -78
- package/src/chat/index.tsx +6 -0
- package/src/helper.tsx +1 -1
- package/src/index.ts +2 -2
- package/src/messages/index.tsx +2 -0
- package/src/messages/message_think.tsx +31 -0
- package/src/messages/messages.stories.tsx +45 -0
- package/src/messages/messages.tsx +32 -8
- package/src/store/index.ts +28 -2
- package/src/store/types.ts +15 -2
- package/src/style.scss +13 -2
- package/src/svgs/think.svg +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @fe-free/ai
|
|
2
2
|
|
|
3
|
+
## 4.1.12
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- feat: ai
|
|
8
|
+
- @fe-free/core@4.1.12
|
|
9
|
+
- @fe-free/icons@4.1.12
|
|
10
|
+
- @fe-free/tool@4.1.12
|
|
11
|
+
|
|
12
|
+
## 4.1.11
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- feat: ai
|
|
17
|
+
- @fe-free/core@4.1.11
|
|
18
|
+
- @fe-free/icons@4.1.11
|
|
19
|
+
- @fe-free/tool@4.1.11
|
|
20
|
+
|
|
3
21
|
## 4.1.10
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fe-free/ai",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.12",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"author": "",
|
|
@@ -15,10 +15,11 @@
|
|
|
15
15
|
"lodash-es": "^4.17.21",
|
|
16
16
|
"uuid": "^13.0.0",
|
|
17
17
|
"zustand": "^4.5.7",
|
|
18
|
-
"@fe-free/core": "4.1.
|
|
18
|
+
"@fe-free/core": "4.1.12"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"@ant-design/x-sdk": "^2.1.3",
|
|
22
|
+
"@ant-design/x": "^2.1.3",
|
|
22
23
|
"antd": "^5.27.1",
|
|
23
24
|
"dayjs": "~1.11.10",
|
|
24
25
|
"i18next": "^25.7.2",
|
|
@@ -26,8 +27,8 @@
|
|
|
26
27
|
"i18next-icu": "^2.4.1",
|
|
27
28
|
"react": "^19.2.0",
|
|
28
29
|
"react-i18next": "^16.4.0",
|
|
29
|
-
"@fe-free/icons": "4.1.
|
|
30
|
-
"@fe-free/tool": "4.1.
|
|
30
|
+
"@fe-free/icons": "4.1.12",
|
|
31
|
+
"@fe-free/tool": "4.1.12"
|
|
31
32
|
},
|
|
32
33
|
"scripts": {
|
|
33
34
|
"test": "echo \"Error: no test specified\" && exit 1",
|
package/src/ai.stories.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Chat,
|
|
4
4
|
createChatStore,
|
|
5
5
|
EnumChatMessageStatus,
|
|
6
|
+
EnumChatMessageType,
|
|
6
7
|
generateUUID,
|
|
7
8
|
MessageActions,
|
|
8
9
|
Messages,
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
} from '@fe-free/ai';
|
|
11
12
|
import { sleep } from '@fe-free/tool';
|
|
12
13
|
import type { Meta } from '@storybook/react-vite';
|
|
14
|
+
import { Button, Divider } from 'antd';
|
|
13
15
|
import { set } from 'lodash-es';
|
|
14
16
|
import { useCallback, useEffect, useMemo } from 'react';
|
|
15
17
|
|
|
@@ -46,38 +48,22 @@ function Component() {
|
|
|
46
48
|
const senderValue = useChatStore((state) => state.senderValue);
|
|
47
49
|
const setSenderValue = useChatStore((state) => state.setSenderValue);
|
|
48
50
|
const messages = useChatStore((state) => state.messages);
|
|
51
|
+
const setMessages = useChatStore((state) => state.setMessages);
|
|
49
52
|
const addMessage = useChatStore((state) => state.addMessage);
|
|
50
53
|
const updateMessage = useChatStore((state) => state.updateMessage);
|
|
51
54
|
const { chatStatus } = useChatStoreComputed();
|
|
52
55
|
|
|
53
|
-
|
|
54
|
-
chatStatus === EnumChatMessageStatus.PENDING || chatStatus === EnumChatMessageStatus.STREAMING;
|
|
55
|
-
|
|
56
|
+
// init from cache
|
|
56
57
|
useEffect(() => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
},
|
|
62
|
-
ai: {
|
|
63
|
-
data: {
|
|
64
|
-
text: '你好,\n我是AI,很高兴认识你',
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
addMessage({
|
|
69
|
-
uuid: generateUUID(),
|
|
70
|
-
user: {
|
|
71
|
-
text: 'hello',
|
|
72
|
-
},
|
|
73
|
-
ai: {
|
|
74
|
-
data: {
|
|
75
|
-
text: '你\n好,\n我\n是\nAI,\n很\n高\n兴\n认\n识\n你\n你\n好,\n我\n是\nAI,\n很\n高\n兴\n认\n识\n你\n很\n高\n兴\n认\n识\n你\n',
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
});
|
|
58
|
+
const cacheMessages = localStorage.getItem('chatMessages');
|
|
59
|
+
if (cacheMessages) {
|
|
60
|
+
setMessages(JSON.parse(cacheMessages));
|
|
61
|
+
}
|
|
79
62
|
}, []);
|
|
80
63
|
|
|
64
|
+
const loading =
|
|
65
|
+
chatStatus === EnumChatMessageStatus.PENDING || chatStatus === EnumChatMessageStatus.STREAMING;
|
|
66
|
+
|
|
81
67
|
const handleSubmit = useCallback((v) => {
|
|
82
68
|
console.log('onSubmit', v);
|
|
83
69
|
|
|
@@ -100,70 +86,101 @@ function Component() {
|
|
|
100
86
|
const preText = message.ai?.data?.text || '';
|
|
101
87
|
set(message, 'ai.data.text', preText + data);
|
|
102
88
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
89
|
+
// 假设有 session_id
|
|
90
|
+
set(message, 'ai.session_id', '123');
|
|
91
|
+
|
|
92
|
+
updateMessage(message);
|
|
106
93
|
}
|
|
107
94
|
if (event === 'done') {
|
|
108
95
|
message.status = EnumChatMessageStatus.DONE;
|
|
109
|
-
updateMessage(
|
|
110
|
-
...message,
|
|
111
|
-
});
|
|
96
|
+
updateMessage(message);
|
|
112
97
|
}
|
|
113
98
|
},
|
|
114
99
|
});
|
|
115
100
|
}, []);
|
|
116
101
|
|
|
117
102
|
return (
|
|
118
|
-
<div
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
103
|
+
<div>
|
|
104
|
+
<div>
|
|
105
|
+
<Button
|
|
106
|
+
onClick={() => {
|
|
107
|
+
addMessage({
|
|
108
|
+
uuid: generateUUID(),
|
|
109
|
+
type: EnumChatMessageType.SYSTEM,
|
|
110
|
+
system: {
|
|
111
|
+
data: {
|
|
112
|
+
type: 'new_session',
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
}}
|
|
117
|
+
>
|
|
118
|
+
Add New Session
|
|
119
|
+
</Button>
|
|
120
|
+
</div>
|
|
121
|
+
<div className="h-[800px] w-[500px] border border-red-500">
|
|
122
|
+
<Chat
|
|
123
|
+
end={
|
|
124
|
+
<div
|
|
125
|
+
className="p-2"
|
|
126
|
+
onFocus={() => {
|
|
127
|
+
console.log('onFocus');
|
|
128
|
+
}}
|
|
129
|
+
onBlur={() => {
|
|
130
|
+
console.log('onBlur');
|
|
131
|
+
}}
|
|
132
|
+
>
|
|
133
|
+
<MSender
|
|
134
|
+
value={senderValue}
|
|
135
|
+
onChange={(v) => setSenderValue(v)}
|
|
136
|
+
loading={loading}
|
|
137
|
+
onSubmit={handleSubmit}
|
|
138
|
+
/>
|
|
139
|
+
</div>
|
|
140
|
+
}
|
|
141
|
+
>
|
|
142
|
+
<Messages
|
|
143
|
+
messages={messages}
|
|
144
|
+
renderMessageOfSystem={({ message }) => {
|
|
145
|
+
if (message.system?.data?.type === 'new_session') {
|
|
146
|
+
return <Divider>让我们聊点新内容吧</Divider>;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return null;
|
|
125
150
|
}}
|
|
126
|
-
|
|
127
|
-
|
|
151
|
+
renderMessageOfUser={({ message }) => {
|
|
152
|
+
return (
|
|
153
|
+
<div className="p-2">
|
|
154
|
+
<div className="rounded-xl bg-primary p-2 text-white">{message.user?.text}</div>
|
|
155
|
+
</div>
|
|
156
|
+
);
|
|
128
157
|
}}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}}
|
|
156
|
-
/>
|
|
157
|
-
<MessageActions.Dislike
|
|
158
|
-
onClick={async () => {
|
|
159
|
-
// some thing
|
|
160
|
-
}}
|
|
161
|
-
/>
|
|
162
|
-
</div>
|
|
163
|
-
</div>
|
|
164
|
-
)}
|
|
165
|
-
/>
|
|
166
|
-
</Chat>
|
|
158
|
+
renderMessageOfAI={({ message }) => {
|
|
159
|
+
return (
|
|
160
|
+
<div className="p-2">
|
|
161
|
+
<div>
|
|
162
|
+
status: {message.status} session_id: {message.ai?.session_id}
|
|
163
|
+
</div>
|
|
164
|
+
<pre className="whitespace-pre-wrap">{message.ai?.data?.text}</pre>
|
|
165
|
+
<div className="flex gap-2">
|
|
166
|
+
<MessageActions.Copy value={message.ai?.data?.text || ''} />
|
|
167
|
+
<MessageActions.Like
|
|
168
|
+
onClick={async () => {
|
|
169
|
+
// some thing
|
|
170
|
+
}}
|
|
171
|
+
/>
|
|
172
|
+
<MessageActions.Dislike
|
|
173
|
+
onClick={async () => {
|
|
174
|
+
// some thing
|
|
175
|
+
}}
|
|
176
|
+
/>
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
);
|
|
180
|
+
}}
|
|
181
|
+
/>
|
|
182
|
+
</Chat>
|
|
183
|
+
</div>
|
|
167
184
|
</div>
|
|
168
185
|
);
|
|
169
186
|
}
|
package/src/chat/index.tsx
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { PageLayout } from '@fe-free/core';
|
|
2
2
|
|
|
3
3
|
function Chat({
|
|
4
|
+
start,
|
|
5
|
+
startClassName,
|
|
4
6
|
end,
|
|
5
7
|
endClassName,
|
|
6
8
|
children,
|
|
7
9
|
childrenClassName,
|
|
8
10
|
}: {
|
|
11
|
+
start?: React.ReactNode;
|
|
12
|
+
startClassName?: string;
|
|
9
13
|
end?: React.ReactNode;
|
|
10
14
|
endClassName?: string;
|
|
11
15
|
children?: React.ReactNode;
|
|
@@ -14,6 +18,8 @@ function Chat({
|
|
|
14
18
|
return (
|
|
15
19
|
<PageLayout
|
|
16
20
|
direction="vertical"
|
|
21
|
+
start={start}
|
|
22
|
+
startClassName={startClassName}
|
|
17
23
|
end={end}
|
|
18
24
|
endClassName={endClassName}
|
|
19
25
|
childrenClassName={childrenClassName}
|
package/src/helper.tsx
CHANGED
|
@@ -30,7 +30,7 @@ function RecordLoading({
|
|
|
30
30
|
style={{
|
|
31
31
|
height: '4px',
|
|
32
32
|
width: '2px',
|
|
33
|
-
animation: `sender-rectangle-${color} infinite 1s ease-in-out ${getAnimationDelay(index)}s`,
|
|
33
|
+
animation: `fea-sender-rectangle-${color} infinite 1s ease-in-out ${getAnimationDelay(index)}s`,
|
|
34
34
|
}}
|
|
35
35
|
/>
|
|
36
36
|
))}
|
package/src/index.ts
CHANGED
|
@@ -4,8 +4,8 @@ export { FileView, FileViewList } from './files';
|
|
|
4
4
|
export { generateUUID } from './helper';
|
|
5
5
|
export { MSender } from './m_sender';
|
|
6
6
|
export type { MSenderProps, MSenderRef } from './m_sender';
|
|
7
|
-
export { MessageActions, Messages } from './messages';
|
|
8
|
-
export type { MessagesProps } from './messages';
|
|
7
|
+
export { MessageActions, MessageThink, Messages } from './messages';
|
|
8
|
+
export type { MessageThinkProps, MessagesProps } from './messages';
|
|
9
9
|
export { Sender } from './sender';
|
|
10
10
|
export type { SenderProps, SenderRef } from './sender';
|
|
11
11
|
export { createChatStore } from './store';
|
package/src/messages/index.tsx
CHANGED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Think } from '@ant-design/x';
|
|
2
|
+
import Icons from '@fe-free/icons';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
import ThinkIcon from '../svgs/think.svg?react';
|
|
5
|
+
|
|
6
|
+
interface MessageThinkProps {
|
|
7
|
+
title: string;
|
|
8
|
+
icon?: React.ReactNode;
|
|
9
|
+
loading?: boolean;
|
|
10
|
+
children?: React.ReactNode;
|
|
11
|
+
type?: 'deepSeek';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function MessageThink({ title, icon, loading, children, type }: MessageThinkProps) {
|
|
15
|
+
return (
|
|
16
|
+
<Think
|
|
17
|
+
title={title}
|
|
18
|
+
icon={icon || <Icons component={ThinkIcon} className="!text-sm" />}
|
|
19
|
+
loading={loading}
|
|
20
|
+
blink={loading}
|
|
21
|
+
className={classNames('fea-message-think', {
|
|
22
|
+
'fea-message-think-deep-seek': type === 'deepSeek',
|
|
23
|
+
})}
|
|
24
|
+
>
|
|
25
|
+
{children}
|
|
26
|
+
</Think>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { MessageThink };
|
|
31
|
+
export type { MessageThinkProps };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { MessageThink } from '@fe-free/ai';
|
|
2
|
+
import { CheckCircleOutlined } from '@fe-free/icons';
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof MessageThink> = {
|
|
6
|
+
title: '@fe-free/ai/MessageThink',
|
|
7
|
+
component: MessageThink,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type Story = StoryObj<typeof MessageThink>;
|
|
12
|
+
|
|
13
|
+
export const Default: Story = {
|
|
14
|
+
args: {
|
|
15
|
+
title: '思考',
|
|
16
|
+
children: '这是 Think 的内容',
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const Loading: Story = {
|
|
21
|
+
args: {
|
|
22
|
+
title: '思考中...',
|
|
23
|
+
loading: true,
|
|
24
|
+
children: '这是 Think 的内容',
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const Icon: Story = {
|
|
29
|
+
args: {
|
|
30
|
+
title: '思考',
|
|
31
|
+
children: '这是 Think 的内容',
|
|
32
|
+
icon: <CheckCircleOutlined className="text-green08" />,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const DeepSeek: Story = {
|
|
37
|
+
args: {
|
|
38
|
+
title: '思考中...',
|
|
39
|
+
loading: true,
|
|
40
|
+
children: '这是 Think 的内容',
|
|
41
|
+
type: 'deepSeek',
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export default meta;
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import { PageLayout } from '@fe-free/core';
|
|
2
2
|
import { useEffect, useMemo, useRef } from 'react';
|
|
3
|
-
import type
|
|
3
|
+
import { EnumChatMessageType, type ChatMessage } from '../store/types';
|
|
4
4
|
|
|
5
5
|
interface MessagesProps<AIData> {
|
|
6
6
|
messages?: ChatMessage<AIData>[];
|
|
7
|
+
/** 含所有 */
|
|
8
|
+
renderMessage?: (props: { message: ChatMessage<AIData> }) => React.ReactNode;
|
|
9
|
+
/** 系统消息 */
|
|
10
|
+
renderMessageOfSystem?: (props: { message: ChatMessage<AIData> }) => React.ReactNode;
|
|
11
|
+
/** 用户消息 */
|
|
7
12
|
renderMessageOfUser?: (props: { message: ChatMessage<AIData> }) => React.ReactNode;
|
|
13
|
+
/** AI消息 */
|
|
8
14
|
renderMessageOfAI?: (props: { message: ChatMessage<AIData> }) => React.ReactNode;
|
|
9
15
|
}
|
|
10
16
|
|
|
11
17
|
function Messages<AIData>(props: MessagesProps<AIData>) {
|
|
12
|
-
const { messages, renderMessageOfUser, renderMessageOfAI } =
|
|
18
|
+
const { messages, renderMessage, renderMessageOfSystem, renderMessageOfUser, renderMessageOfAI } =
|
|
19
|
+
props;
|
|
13
20
|
|
|
14
21
|
const ref = useRef<HTMLDivElement>(null);
|
|
15
22
|
|
|
@@ -53,12 +60,29 @@ function Messages<AIData>(props: MessagesProps<AIData>) {
|
|
|
53
60
|
return (
|
|
54
61
|
<PageLayout>
|
|
55
62
|
<div ref={ref} className="flex h-full flex-col overflow-y-auto">
|
|
56
|
-
{messages?.map((message) =>
|
|
57
|
-
|
|
58
|
-
<div className="flex
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
{messages?.map((message) => {
|
|
64
|
+
return (
|
|
65
|
+
<div key={message.uuid} data-uuid={message.uuid} className="flex flex-col">
|
|
66
|
+
{renderMessage ? (
|
|
67
|
+
renderMessage?.({ message })
|
|
68
|
+
) : (
|
|
69
|
+
<>
|
|
70
|
+
{message.type === EnumChatMessageType.SYSTEM && message.system && (
|
|
71
|
+
<div className="flex justify-center">
|
|
72
|
+
{renderMessageOfSystem?.({ message })}
|
|
73
|
+
</div>
|
|
74
|
+
)}
|
|
75
|
+
{message.type !== EnumChatMessageType.SYSTEM && message.user && (
|
|
76
|
+
<div className="flex justify-end">{renderMessageOfUser?.({ message })}</div>
|
|
77
|
+
)}
|
|
78
|
+
{message.type !== EnumChatMessageType.SYSTEM && message.ai && (
|
|
79
|
+
<div className="flex justify-start">{renderMessageOfAI?.({ message })}</div>
|
|
80
|
+
)}
|
|
81
|
+
</>
|
|
82
|
+
)}
|
|
83
|
+
</div>
|
|
84
|
+
);
|
|
85
|
+
})}
|
|
62
86
|
</div>
|
|
63
87
|
</PageLayout>
|
|
64
88
|
);
|
package/src/store/index.ts
CHANGED
|
@@ -2,30 +2,51 @@ import { useMemo } from 'react';
|
|
|
2
2
|
import { create } from 'zustand';
|
|
3
3
|
import type { ChatMessage } from './types';
|
|
4
4
|
|
|
5
|
-
interface
|
|
5
|
+
interface BaseSenderValue {
|
|
6
|
+
text?: string;
|
|
7
|
+
files?: string[];
|
|
8
|
+
}
|
|
9
|
+
interface ChatStore<Value extends BaseSenderValue | undefined, AIData, ContextData = any> {
|
|
6
10
|
senderValue?: Value;
|
|
7
11
|
setSenderValue: (senderValue?: Value) => void;
|
|
8
12
|
|
|
9
13
|
messages: ChatMessage<AIData>[];
|
|
14
|
+
setMessages: (messages: ChatMessage<AIData>[]) => void;
|
|
10
15
|
addMessage: (message: ChatMessage<AIData>) => void;
|
|
11
16
|
updateMessage: (message: ChatMessage<AIData>) => void;
|
|
12
17
|
|
|
18
|
+
/** 存放Chat的上下文数据 */
|
|
19
|
+
contextData?: ContextData;
|
|
20
|
+
setContextData: (contextData?: ContextData) => void;
|
|
21
|
+
|
|
13
22
|
reset: () => void;
|
|
14
23
|
}
|
|
15
24
|
|
|
16
|
-
function createChatStore<Value, AIData>() {
|
|
25
|
+
function createChatStore<Value extends BaseSenderValue | undefined, AIData>() {
|
|
17
26
|
const useChatStore = create<ChatStore<Value, AIData>>((set, get, store) => ({
|
|
18
27
|
senderValue: undefined,
|
|
19
28
|
setSenderValue: (senderValue) => {
|
|
20
29
|
set(() => ({ senderValue }));
|
|
21
30
|
},
|
|
22
31
|
messages: [],
|
|
32
|
+
setMessages: (messages) => {
|
|
33
|
+
set(() => ({
|
|
34
|
+
messages: messages.map((message) => ({
|
|
35
|
+
// 如果没有,则用当前的时间
|
|
36
|
+
createdAt: Date.now(),
|
|
37
|
+
updatedAt: Date.now(),
|
|
38
|
+
...message,
|
|
39
|
+
})),
|
|
40
|
+
}));
|
|
41
|
+
},
|
|
23
42
|
addMessage: (message) => {
|
|
24
43
|
set((state) => ({
|
|
25
44
|
messages: [
|
|
26
45
|
...state.messages,
|
|
27
46
|
{
|
|
28
47
|
...message,
|
|
48
|
+
// 覆盖
|
|
49
|
+
createdAt: Date.now(),
|
|
29
50
|
updatedAt: Date.now(),
|
|
30
51
|
},
|
|
31
52
|
],
|
|
@@ -37,6 +58,7 @@ function createChatStore<Value, AIData>() {
|
|
|
37
58
|
if (m.uuid === message.uuid) {
|
|
38
59
|
return {
|
|
39
60
|
...message,
|
|
61
|
+
// 覆盖
|
|
40
62
|
updatedAt: Date.now(),
|
|
41
63
|
};
|
|
42
64
|
}
|
|
@@ -44,6 +66,10 @@ function createChatStore<Value, AIData>() {
|
|
|
44
66
|
}),
|
|
45
67
|
}));
|
|
46
68
|
},
|
|
69
|
+
contextData: undefined,
|
|
70
|
+
setContextData: (contextData) => {
|
|
71
|
+
set(() => ({ contextData }));
|
|
72
|
+
},
|
|
47
73
|
reset: () => {
|
|
48
74
|
set(store.getInitialState());
|
|
49
75
|
},
|
package/src/store/types.ts
CHANGED
|
@@ -9,6 +9,10 @@ enum EnumChatMessageStatus {
|
|
|
9
9
|
ERROR = 'error',
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
interface ChatMessageOfSystem {
|
|
13
|
+
data?: any;
|
|
14
|
+
}
|
|
15
|
+
|
|
12
16
|
interface ChatMessageOfUser {
|
|
13
17
|
text?: string;
|
|
14
18
|
files?: string[];
|
|
@@ -16,15 +20,24 @@ interface ChatMessageOfUser {
|
|
|
16
20
|
|
|
17
21
|
interface ChatMessageOfAI<AIData> {
|
|
18
22
|
data?: AIData;
|
|
23
|
+
/** 按需存取 */
|
|
24
|
+
session_id?: string;
|
|
19
25
|
}
|
|
20
26
|
|
|
21
27
|
interface ChatMessage<AIData> {
|
|
22
28
|
uuid: string;
|
|
23
|
-
|
|
24
|
-
type?: EnumChatMessageType;
|
|
29
|
+
|
|
25
30
|
status?: EnumChatMessageStatus;
|
|
31
|
+
|
|
32
|
+
type?: EnumChatMessageType;
|
|
33
|
+
system?: ChatMessageOfSystem;
|
|
26
34
|
user?: ChatMessageOfUser;
|
|
27
35
|
ai?: ChatMessageOfAI<AIData>;
|
|
36
|
+
|
|
37
|
+
/** 自动生成 */
|
|
38
|
+
createdAt?: number;
|
|
39
|
+
/** 自动更新 */
|
|
40
|
+
updatedAt?: number;
|
|
28
41
|
}
|
|
29
42
|
|
|
30
43
|
export { EnumChatMessageStatus, EnumChatMessageType };
|
package/src/style.scss
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
@keyframes sender-rectangle-white {
|
|
1
|
+
@keyframes fea-sender-rectangle-white {
|
|
2
2
|
0%,
|
|
3
3
|
80%,
|
|
4
4
|
100% {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
@keyframes sender-rectangle-primary {
|
|
15
|
+
@keyframes fea-sender-rectangle-primary {
|
|
16
16
|
0%,
|
|
17
17
|
80%,
|
|
18
18
|
100% {
|
|
@@ -25,3 +25,14 @@
|
|
|
25
25
|
box-shadow: 0 -8px theme('colors.primary');
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
+
|
|
29
|
+
.fea-message-think {
|
|
30
|
+
&:not(.fea-message-think-deep-seek) {
|
|
31
|
+
.ant-think-content {
|
|
32
|
+
border-inline-start: none;
|
|
33
|
+
background-color: theme('backgroundColor.01');
|
|
34
|
+
padding: 12px 16px;
|
|
35
|
+
border-radius: 8px;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M9.80022 0.000346623C10.3956 -0.0083669 10.97 0.146298 11.3912 0.566726C11.8123 0.987879 11.9677 1.56297 11.9583 2.1584C11.9496 2.75164 11.7782 3.41387 11.4935 4.09352C11.2145 4.7429 10.8741 5.36414 10.477 5.94878C10.9214 6.60592 11.2793 7.25436 11.5349 7.86575C11.8196 8.54541 11.9902 9.20764 11.9997 9.80088C12.0084 10.3963 11.853 10.9707 11.4326 11.3911C11.0114 11.8123 10.4363 11.9684 9.84088 11.9589C9.24763 11.9502 8.58613 11.7789 7.90575 11.4942C7.29726 11.2401 6.65318 10.8843 5.99894 10.4428C5.34543 10.8843 4.70135 11.2401 4.09286 11.4942C3.4132 11.7789 2.75097 11.9502 2.15773 11.9589C1.5623 11.9684 0.987938 11.8123 0.566784 11.3918C0.14563 10.9707 -0.00903481 10.3963 0.000404838 9.80088C0.00911836 9.20691 0.179032 8.54541 0.463674 7.86575C0.719271 7.25436 1.0758 6.60592 1.52019 5.94878C1.12348 5.36412 0.783555 4.74287 0.505063 4.09352C0.220421 3.41387 0.0505076 2.75164 0.041068 2.1584C0.0323545 1.56297 0.186293 0.988605 0.607447 0.567452C1.0286 0.146298 1.60369 -0.00836689 2.19912 0.00107276C2.79236 0.00978629 3.45387 0.1797 4.13425 0.464342C4.72967 0.713403 5.35922 1.05831 5.99894 1.486C6.63866 1.05759 7.26966 0.713403 7.86509 0.464342C8.54474 0.1797 9.20624 0.00978628 9.80022 0.000346623ZM2.20638 6.89057C1.9225 7.33469 1.67575 7.80148 1.46863 8.28618C1.21667 8.88887 1.09468 9.40805 1.08814 9.81686C1.08233 10.2235 1.18835 10.4733 1.33648 10.6214C1.48533 10.7695 1.73585 10.8756 2.14175 10.8697C2.55056 10.8639 3.06974 10.7419 3.67243 10.49C4.15456 10.2835 4.61891 10.0377 5.06078 9.75514C4.53958 9.34105 4.04257 8.89738 3.57222 8.42632C3.0712 7.9253 2.61374 7.40829 2.20638 6.89057ZM9.7915 6.89057C8.95508 7.9533 7.99736 8.91467 6.93782 9.75514C7.4207 10.0601 7.88905 10.307 8.32618 10.49C8.92886 10.7419 9.44877 10.8639 9.85758 10.8697C10.2642 10.8763 10.514 10.7703 10.6621 10.6214C10.8103 10.4733 10.9163 10.2235 10.9105 9.81686C10.9039 9.40805 10.7819 8.88814 10.53 8.28618C10.3226 7.80147 10.0756 7.33468 9.7915 6.89057ZM5.99894 2.82208C5.39911 3.27502 4.83182 3.76951 4.30126 4.30192C3.78316 4.81841 3.30086 5.36961 2.85772 5.95168C3.31201 6.55419 3.80822 7.12392 4.34264 7.65663C4.86105 8.1765 5.41444 8.66026 5.99894 9.10453C6.5508 8.687 7.10992 8.20268 7.65596 7.65663C8.18989 7.12387 8.68561 6.55414 9.13944 5.95168C8.69678 5.36964 8.21497 4.81845 7.69735 4.30192C7.13824 3.74281 6.56459 3.24686 5.99894 2.82208ZM2.18242 1.08881C1.77579 1.083 1.526 1.18902 1.37787 1.33715C1.22974 1.486 1.12372 1.73579 1.12953 2.14242C1.13607 2.55123 1.25806 3.07041 1.51002 3.6731C1.68647 4.09498 1.92174 4.54445 2.21074 5.00917C2.62264 4.4922 3.06362 3.99909 3.53156 3.53223C4.01281 3.05013 4.52198 2.59673 5.05643 2.17437C4.5888 1.88319 4.13715 1.64648 3.71309 1.4693C3.11041 1.21734 2.59123 1.09535 2.18242 1.08881ZM9.81619 1.08881C9.40738 1.09607 8.88748 1.21734 8.28552 1.4693C7.86146 1.64648 7.40908 1.88319 6.94218 2.17365C7.47661 2.59602 7.98578 3.04942 8.46705 3.5315C8.93477 3.99886 9.37552 4.49245 9.78715 5.0099C10.0761 4.54518 10.3136 4.0957 10.49 3.67382C10.742 3.07114 10.864 2.55196 10.8698 2.14315C10.8763 1.73652 10.7703 1.48673 10.6215 1.33787C10.4733 1.18974 10.2235 1.08373 9.81692 1.08954L9.81619 1.08881Z"/>
|
|
3
|
+
</svg>
|