@lobehub/chat 0.25.0 → 0.26.1
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/.eslintrc.js +2 -1
- package/CHANGELOG.md +113 -6
- package/package.json +2 -5
- package/src/config/server.ts +22 -0
- package/src/const/fetch.ts +2 -2
- package/src/const/message.ts +2 -0
- package/src/locales/create.ts +3 -14
- package/src/locales/default/common.ts +4 -0
- package/src/locales/default/error.ts +27 -0
- package/src/locales/default/plugin.ts +19 -1
- package/src/locales/resources/zh_CN.ts +2 -0
- package/src/pages/api/auth.ts +25 -0
- package/src/pages/api/error.ts +21 -0
- package/src/pages/api/openai.api.ts +11 -5
- package/src/pages/api/openai.ts +24 -9
- package/src/pages/api/plugins.api.ts +11 -36
- package/src/pages/chat/[id]/Conversation/ChatList/Error/ApiKeyForm.tsx +40 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Error/ErrorActionContainer.tsx +23 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Error/InvalidAccess.tsx +76 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Error/OpenAiBizError.tsx +52 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Error/style.tsx +44 -0
- package/src/pages/chat/[id]/Conversation/{MessageExtra.tsx → ChatList/MessageExtra.tsx} +28 -26
- package/src/pages/chat/[id]/Conversation/ChatList/OTPInput.tsx +142 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Plugins/FunctionCall.tsx +60 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Plugins/PluginMessage.tsx +45 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Plugins/PluginResultRender.tsx +51 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Plugins/style.ts +25 -0
- package/src/pages/chat/[id]/Conversation/ChatList/index.tsx +112 -0
- package/src/pages/chat/[id]/Conversation/Input/Token.tsx +1 -1
- package/src/pages/chat/[id]/edit/AgentPlugin/index.tsx +2 -2
- package/src/pages/setting/Header.tsx +2 -2
- package/src/pages/setting/index.page.tsx +11 -28
- package/src/pages/setting/layout.tsx +35 -0
- package/src/plugins/Render.ts +8 -0
- package/src/plugins/index.ts +7 -3
- package/src/plugins/searchEngine/index.ts +4 -1
- package/src/plugins/searchEngine/runner.ts +5 -73
- package/src/plugins/searchEngine/type.ts +80 -0
- package/src/plugins/type.ts +17 -0
- package/src/plugins/weather/Render.tsx +53 -0
- package/src/plugins/weather/index.ts +9 -1
- package/src/plugins/weather/runner.ts +12 -7
- package/src/plugins/weather/type.ts +36 -0
- package/src/plugins/webCrawler/index.ts +4 -1
- package/src/plugins/webCrawler/runner.ts +3 -27
- package/src/plugins/webCrawler/type.ts +32 -0
- package/src/services/chatModel.ts +3 -3
- package/src/services/plugin.ts +30 -0
- package/src/store/session/slices/chat/actions/message.ts +61 -42
- package/src/store/session/slices/chat/initialState.ts +2 -4
- package/src/store/session/slices/chat/selectors/utils.test.ts +3 -2
- package/src/store/session/slices/chat/selectors/utils.ts +4 -3
- package/src/types/chatMessage.ts +9 -6
- package/src/types/fetch.ts +26 -0
- package/src/types/openai.ts +3 -0
- package/src/types/plugin.ts +4 -0
- package/src/utils/fetch.ts +21 -25
- package/src/utils/message.ts +16 -0
- package/src/pages/chat/[id]/Conversation/ChatList.tsx +0 -69
- package/src/pages/chat/[id]/Conversation/FunctionMessage.tsx +0 -31
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { StateCreator } from 'zustand/vanilla';
|
|
2
2
|
|
|
3
3
|
import { fetchChatModel } from '@/services/chatModel';
|
|
4
|
+
import { fetchPlugin } from '@/services/plugin';
|
|
4
5
|
import { SessionStore, agentSelectors, chatSelectors, sessionSelectors } from '@/store/session';
|
|
5
|
-
import { ChatMessage } from '@/types/chatMessage';
|
|
6
|
+
import { ChatMessage, OpenAIFunctionCall } from '@/types/chatMessage';
|
|
6
7
|
import { fetchSSE } from '@/utils/fetch';
|
|
7
8
|
import { isFunctionMessage } from '@/utils/message';
|
|
8
9
|
import { nanoid } from '@/utils/uuid';
|
|
@@ -42,8 +43,7 @@ export interface ChatMessageAction {
|
|
|
42
43
|
generateMessage: (
|
|
43
44
|
messages: ChatMessage[],
|
|
44
45
|
assistantMessageId: string,
|
|
45
|
-
|
|
46
|
-
) => Promise<{ isFunctionCall: boolean; output: string }>;
|
|
46
|
+
) => Promise<{ isFunctionCall: boolean }>;
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* 实际获取 AI 响应
|
|
@@ -63,6 +63,7 @@ export interface ChatMessageAction {
|
|
|
63
63
|
* @param text - 消息文本
|
|
64
64
|
*/
|
|
65
65
|
sendMessage: (text: string) => Promise<void>;
|
|
66
|
+
triggerFunctionCall: (id: string) => Promise<void>;
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
export const chatMessage: StateCreator<
|
|
@@ -108,16 +109,13 @@ export const chatMessage: StateCreator<
|
|
|
108
109
|
get().dispatchSession({ chats, id: activeId, type: 'updateSessionChat' });
|
|
109
110
|
},
|
|
110
111
|
|
|
111
|
-
generateMessage: async (messages, assistantId
|
|
112
|
+
generateMessage: async (messages, assistantId) => {
|
|
112
113
|
const { dispatchMessage } = get();
|
|
113
|
-
set({
|
|
114
|
+
set({ chatLoadingId: assistantId });
|
|
114
115
|
const config = agentSelectors.currentAgentConfigSafe(get());
|
|
115
116
|
|
|
116
117
|
const fetcher = () =>
|
|
117
|
-
fetchChatModel(
|
|
118
|
-
{ messages, model: config.model, ...config.params, plugins: config.plugins },
|
|
119
|
-
{ withPlugin },
|
|
120
|
-
);
|
|
118
|
+
fetchChatModel({ messages, model: config.model, ...config.params, plugins: config.plugins });
|
|
121
119
|
|
|
122
120
|
let output = '';
|
|
123
121
|
let isFunctionCall = false;
|
|
@@ -139,13 +137,6 @@ export const chatMessage: StateCreator<
|
|
|
139
137
|
// 如果是 function call
|
|
140
138
|
if (isFunctionMessage(output)) {
|
|
141
139
|
isFunctionCall = true;
|
|
142
|
-
// 设为 function
|
|
143
|
-
dispatchMessage({
|
|
144
|
-
id: assistantId,
|
|
145
|
-
key: 'role',
|
|
146
|
-
type: 'updateMessage',
|
|
147
|
-
value: 'function',
|
|
148
|
-
});
|
|
149
140
|
}
|
|
150
141
|
|
|
151
142
|
// 滚动到最后一条消息
|
|
@@ -156,13 +147,13 @@ export const chatMessage: StateCreator<
|
|
|
156
147
|
},
|
|
157
148
|
});
|
|
158
149
|
|
|
159
|
-
set({
|
|
150
|
+
set({ chatLoadingId: undefined });
|
|
160
151
|
|
|
161
|
-
return { isFunctionCall
|
|
152
|
+
return { isFunctionCall };
|
|
162
153
|
},
|
|
163
154
|
|
|
164
155
|
realFetchAIResponse: async (messages, userMessageId) => {
|
|
165
|
-
const { dispatchMessage, generateMessage, activeTopicId } = get();
|
|
156
|
+
const { dispatchMessage, generateMessage, triggerFunctionCall, activeTopicId } = get();
|
|
166
157
|
|
|
167
158
|
// 添加 systemRole
|
|
168
159
|
const { systemRole, model } = agentSelectors.currentAgentConfigSafe(get());
|
|
@@ -191,31 +182,11 @@ export const chatMessage: StateCreator<
|
|
|
191
182
|
dispatchMessage({ id: mid, key: 'fromModel', type: 'updateMessageExtra', value: model });
|
|
192
183
|
|
|
193
184
|
// 生成 ai message
|
|
194
|
-
const {
|
|
185
|
+
const { isFunctionCall } = await generateMessage(messages, mid);
|
|
195
186
|
|
|
196
187
|
// 如果是 function,则发送函数调用方法
|
|
197
188
|
if (isFunctionCall) {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
dispatchMessage({
|
|
201
|
-
id: mid,
|
|
202
|
-
key: 'function_call',
|
|
203
|
-
type: 'updateMessage',
|
|
204
|
-
value: function_call,
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
await generateMessage(
|
|
208
|
-
[...messages, { content: '', function_call, id: mid, role: 'assistant' } as ChatMessage],
|
|
209
|
-
mid,
|
|
210
|
-
true,
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
dispatchMessage({
|
|
214
|
-
id: mid,
|
|
215
|
-
key: 'role',
|
|
216
|
-
type: 'updateMessage',
|
|
217
|
-
value: 'assistant',
|
|
218
|
-
});
|
|
189
|
+
triggerFunctionCall(mid);
|
|
219
190
|
}
|
|
220
191
|
},
|
|
221
192
|
|
|
@@ -245,7 +216,6 @@ export const chatMessage: StateCreator<
|
|
|
245
216
|
|
|
246
217
|
await realFetchAIResponse(histories, latestMsg.id);
|
|
247
218
|
},
|
|
248
|
-
|
|
249
219
|
sendMessage: async (message) => {
|
|
250
220
|
const { dispatchMessage, realFetchAIResponse, autocompleteSessionAgentMeta, activeTopicId } =
|
|
251
221
|
get();
|
|
@@ -270,4 +240,53 @@ export const chatMessage: StateCreator<
|
|
|
270
240
|
autocompleteSessionAgentMeta(session.id);
|
|
271
241
|
}
|
|
272
242
|
},
|
|
243
|
+
|
|
244
|
+
triggerFunctionCall: async (id) => {
|
|
245
|
+
const { dispatchMessage, generateMessage } = get();
|
|
246
|
+
const session = sessionSelectors.currentSession(get());
|
|
247
|
+
|
|
248
|
+
if (!session) return;
|
|
249
|
+
|
|
250
|
+
const message = session.chats[id];
|
|
251
|
+
if (!message) return;
|
|
252
|
+
|
|
253
|
+
let payload: OpenAIFunctionCall = { name: '' };
|
|
254
|
+
if (message.content) {
|
|
255
|
+
const { function_call } = JSON.parse(message.content);
|
|
256
|
+
dispatchMessage({ id, key: 'function_call', type: 'updateMessage', value: function_call });
|
|
257
|
+
dispatchMessage({ id, key: 'content', type: 'updateMessage', value: '' });
|
|
258
|
+
payload = function_call;
|
|
259
|
+
} else {
|
|
260
|
+
if (message.function_call) {
|
|
261
|
+
payload = message.function_call;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (!payload.name) return;
|
|
266
|
+
|
|
267
|
+
// const fid = nanoid();
|
|
268
|
+
dispatchMessage({ id, key: 'role', type: 'updateMessage', value: 'function' });
|
|
269
|
+
dispatchMessage({ id, key: 'name', type: 'updateMessage', value: payload.name });
|
|
270
|
+
dispatchMessage({ id, key: 'function_call', type: 'updateMessage', value: payload });
|
|
271
|
+
|
|
272
|
+
// dispatchMessage({
|
|
273
|
+
// id: id,
|
|
274
|
+
// message: FUNCTION_LOADING,
|
|
275
|
+
// parentId: message.,
|
|
276
|
+
// role: 'function',
|
|
277
|
+
// type: 'addMessage',
|
|
278
|
+
// });
|
|
279
|
+
|
|
280
|
+
const data = await fetchPlugin(payload);
|
|
281
|
+
|
|
282
|
+
dispatchMessage({ id, key: 'content', type: 'updateMessage', value: data });
|
|
283
|
+
|
|
284
|
+
const mid = nanoid();
|
|
285
|
+
|
|
286
|
+
dispatchMessage({ id: mid, message: LOADING_FLAT, role: 'assistant', type: 'addMessage' });
|
|
287
|
+
|
|
288
|
+
const chats = chatSelectors.currentChats(get());
|
|
289
|
+
|
|
290
|
+
await generateMessage(chats, mid);
|
|
291
|
+
},
|
|
273
292
|
});
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export interface ChatState {
|
|
2
2
|
activeTopicId?: string;
|
|
3
|
-
|
|
3
|
+
chatLoadingId?: string;
|
|
4
4
|
topicLoadingId?: string;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export const initialChatState: ChatState = {
|
|
8
|
-
chatLoading: false,
|
|
9
|
-
};
|
|
7
|
+
export const initialChatState: ChatState = {};
|
|
@@ -295,7 +295,7 @@ describe('organizeChats', () => {
|
|
|
295
295
|
const result = organizeChats(session, avatar);
|
|
296
296
|
const meta = result[0].meta;
|
|
297
297
|
|
|
298
|
-
expect(meta.avatar).toBe(avatar
|
|
298
|
+
expect(meta.avatar).toBe('assistant-avatar');
|
|
299
299
|
expect(meta.title).toBeUndefined();
|
|
300
300
|
});
|
|
301
301
|
|
|
@@ -329,6 +329,7 @@ describe('organizeChats', () => {
|
|
|
329
329
|
function_call: {
|
|
330
330
|
name: 'realtimeWeather',
|
|
331
331
|
},
|
|
332
|
+
name: 'realtimeWeather',
|
|
332
333
|
} as ChatMessage;
|
|
333
334
|
|
|
334
335
|
session.chats[message.id] = message;
|
|
@@ -336,7 +337,7 @@ describe('organizeChats', () => {
|
|
|
336
337
|
const result = organizeChats(session, avatar);
|
|
337
338
|
const meta = result[3].meta;
|
|
338
339
|
|
|
339
|
-
expect(meta.avatar).toBe('
|
|
340
|
+
expect(meta.avatar).toBe('🧩');
|
|
340
341
|
expect(meta.title).toBe('realtimeWeather');
|
|
341
342
|
});
|
|
342
343
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { PluginsMap } from '@/plugins';
|
|
2
2
|
import { ChatMessage } from '@/types/chatMessage';
|
|
3
3
|
import { LobeAgentSession } from '@/types/session';
|
|
4
4
|
|
|
@@ -27,9 +27,10 @@ export const organizeChats = (
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
case 'function': {
|
|
30
|
-
const plugin =
|
|
30
|
+
const plugin = PluginsMap[message.name || ''];
|
|
31
|
+
|
|
31
32
|
return {
|
|
32
|
-
avatar:
|
|
33
|
+
avatar: '🧩',
|
|
33
34
|
title: plugin?.name || 'plugin-unknown',
|
|
34
35
|
};
|
|
35
36
|
}
|
package/src/types/chatMessage.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ErrorType } from '@/types/fetch';
|
|
2
|
+
|
|
1
3
|
import { LLMRoleType } from './llm';
|
|
2
4
|
import { BaseDataModel } from './meta';
|
|
3
5
|
|
|
@@ -5,12 +7,13 @@ import { BaseDataModel } from './meta';
|
|
|
5
7
|
* 聊天消息错误对象
|
|
6
8
|
*/
|
|
7
9
|
export interface ChatMessageError {
|
|
8
|
-
|
|
9
|
-
* 错误信息
|
|
10
|
-
*/
|
|
10
|
+
body?: any;
|
|
11
11
|
message: string;
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
type: ErrorType;
|
|
13
|
+
}
|
|
14
|
+
export interface OpenAIFunctionCall {
|
|
15
|
+
arguments?: string;
|
|
16
|
+
name: string;
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
export interface ChatMessage extends BaseDataModel {
|
|
@@ -30,7 +33,7 @@ export interface ChatMessage extends BaseDataModel {
|
|
|
30
33
|
};
|
|
31
34
|
} & Record<string, any>;
|
|
32
35
|
|
|
33
|
-
function_call?:
|
|
36
|
+
function_call?: OpenAIFunctionCall;
|
|
34
37
|
name?: string;
|
|
35
38
|
|
|
36
39
|
parentId?: string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export enum ErrorType {
|
|
2
|
+
// ******* 业务错误语义 ******* //
|
|
3
|
+
|
|
4
|
+
// 密码无效
|
|
5
|
+
InvalidAccessCode = 'InvalidAccessCode',
|
|
6
|
+
// OpenAI 返回的业务错误
|
|
7
|
+
OpenAIBizError = 'OpenAIBizError',
|
|
8
|
+
|
|
9
|
+
// ******* 客户端错误 ******* //
|
|
10
|
+
BadRequest = 400,
|
|
11
|
+
Unauthorized = 401,
|
|
12
|
+
Forbidden = 403,
|
|
13
|
+
ContentNotFound = 404, // 没找到接口
|
|
14
|
+
TooManyRequests = 429,
|
|
15
|
+
|
|
16
|
+
// ******* 服务端错误 ******* //
|
|
17
|
+
InternalServerError = 500,
|
|
18
|
+
BadGateway = 502,
|
|
19
|
+
ServiceUnavailable = 503,
|
|
20
|
+
GatewayTimeout = 504,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ErrorResponse {
|
|
24
|
+
body: any;
|
|
25
|
+
errorType: ErrorType;
|
|
26
|
+
}
|
package/src/types/openai.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OpenAIFunctionCall } from '@/types/chatMessage';
|
|
1
2
|
import { LLMRoleType } from '@/types/llm';
|
|
2
3
|
|
|
3
4
|
export interface OpenAIChatMessage {
|
|
@@ -7,6 +8,8 @@ export interface OpenAIChatMessage {
|
|
|
7
8
|
*/
|
|
8
9
|
content: string;
|
|
9
10
|
|
|
11
|
+
function_call?: OpenAIFunctionCall;
|
|
12
|
+
name?: string;
|
|
10
13
|
/**
|
|
11
14
|
* 角色
|
|
12
15
|
* @description 消息发送者的角色
|
package/src/utils/fetch.ts
CHANGED
|
@@ -1,24 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { t } from 'i18next';
|
|
2
|
+
|
|
2
3
|
import { fetchChatModel } from '@/services/chatModel';
|
|
3
4
|
import { ChatMessageError } from '@/types/chatMessage';
|
|
4
|
-
|
|
5
|
-
const codeMessage: Record<number, string> = {
|
|
6
|
-
200: '成功获取数据,服务已响应',
|
|
7
|
-
201: '操作成功,数据已保存',
|
|
8
|
-
202: '您的请求已进入后台排队,请耐心等待异步任务完成',
|
|
9
|
-
204: '数据已成功删除',
|
|
10
|
-
400: '很抱歉,您的请求出错,服务器未执行任何数据的创建或修改操作',
|
|
11
|
-
401: '很抱歉,您的权限不足。请确认用户名或密码是否正确',
|
|
12
|
-
403: '很抱歉,您无权访问此内容',
|
|
13
|
-
404: '很抱歉,您请求的记录不存在,服务器未能执行任何操作',
|
|
14
|
-
406: '很抱歉,服务器不支持该请求格式',
|
|
15
|
-
410: '很抱歉,你所请求的资源已永久删除',
|
|
16
|
-
422: '很抱歉,在创建对象时遇到验证错误,请稍后再试',
|
|
17
|
-
500: '很抱歉,服务器出现了问题,请稍后再试',
|
|
18
|
-
502: '很抱歉,您遇到了网关错误。这可能是由于网络故障或服务器问题导致的。请稍后再试,或联系管理员以获取更多帮助',
|
|
19
|
-
503: '很抱歉,我们的服务器过载或处在维护中,服务暂时不可用',
|
|
20
|
-
504: '很抱歉,网关请求超时,请稍后再试',
|
|
21
|
-
};
|
|
5
|
+
import { ErrorResponse } from '@/types/fetch';
|
|
22
6
|
|
|
23
7
|
export interface FetchSSEOptions {
|
|
24
8
|
onErrorHandle?: (error: ChatMessageError) => void;
|
|
@@ -33,13 +17,25 @@ export interface FetchSSEOptions {
|
|
|
33
17
|
export const fetchSSE = async (fetchFn: () => Promise<Response>, options: FetchSSEOptions = {}) => {
|
|
34
18
|
const response = await fetchFn();
|
|
35
19
|
|
|
36
|
-
// 如果不 ok
|
|
20
|
+
// 如果不 ok 说明有请求错误
|
|
37
21
|
if (!response.ok) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
22
|
+
let chatMessageError: ChatMessageError;
|
|
23
|
+
|
|
24
|
+
// 尝试取一波业务错误语义
|
|
25
|
+
try {
|
|
26
|
+
const data = (await response.json()) as ErrorResponse;
|
|
27
|
+
chatMessageError = {
|
|
28
|
+
body: data.body,
|
|
29
|
+
message: t(`response.${data.errorType}`),
|
|
30
|
+
type: data.errorType,
|
|
31
|
+
};
|
|
32
|
+
} catch {
|
|
33
|
+
// 如果无法正常返回,说明是常规报错
|
|
34
|
+
chatMessageError = {
|
|
35
|
+
message: t(`response.${response.status}`),
|
|
36
|
+
type: response.status,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
43
39
|
|
|
44
40
|
options.onErrorHandle?.(chatMessageError);
|
|
45
41
|
return;
|
package/src/utils/message.ts
CHANGED
|
@@ -3,3 +3,19 @@ import { FUNCTION_MESSAGE_FLAG } from '@/const/message';
|
|
|
3
3
|
export const isFunctionMessage = (content: string) => {
|
|
4
4
|
return content.startsWith(FUNCTION_MESSAGE_FLAG);
|
|
5
5
|
};
|
|
6
|
+
|
|
7
|
+
// export const createFunctionCallMessage = () => {
|
|
8
|
+
// return [
|
|
9
|
+
// {
|
|
10
|
+
// content: '',
|
|
11
|
+
// function_call: { arguments: '{\n "city": "杭州"\n}', name: 'realtimeWeather' },
|
|
12
|
+
// role: 'assistant',
|
|
13
|
+
// },
|
|
14
|
+
// {
|
|
15
|
+
// content:
|
|
16
|
+
// '{"status":"1","count":"1","info":"OK","infocode":"10000","forecasts":[{"city":"杭州市","adcode":"300","province":"浙江","reporttime":"2023-07-28 20:32:48","casts":[{"date":"2023-07-28","week":"5","dayweather"小雨","nightweather":"小雨-中雨","daytemp":"32","nighttemp":"26","daywind":"东","nightwind":"东","daypower":"6power":"6","daytemp_float":"32.0","nighttemp_float":"26.0"},{"date":"2023-07-29","week":"6","dayweather":"小雨雨","nightweather":"小雨","daytemp":"30","nighttemp":"25","daywind":"东南","nightwind":"东南","daypower":"4","wer":"4","daytemp_float":"30.0","nighttemp_float":"25.0"},{"date":"2023-07-30","week":"7","dayweather":"小雨",ightweather":"雷阵雨","daytemp":"31","nighttemp":"25","daywind":"东南","nightwind":"东南","daypower":"4","nigh:"4","daytemp_float":"31.0","nighttemp_float":"25.0"},{"date":"2023-07-31","week":"1","dayweather":"雷阵雨","ntweather":"雷阵雨","daytemp":"33","nighttemp":"25","daywind":"东","nightwind":"东","daypower":"4","nightpower""daytemp_float":"33.0","nighttemp_float":"25.0"}]}]}',
|
|
17
|
+
// name: 'realtimeWeather',
|
|
18
|
+
// role: 'function',
|
|
19
|
+
// },
|
|
20
|
+
// ];
|
|
21
|
+
// };
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { ChatList, ChatMessage } from '@lobehub/ui';
|
|
2
|
-
import isEqual from 'fast-deep-equal';
|
|
3
|
-
import { ReactNode, memo } from 'react';
|
|
4
|
-
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import { shallow } from 'zustand/shallow';
|
|
6
|
-
|
|
7
|
-
import { agentSelectors, chatSelectors, useSessionStore } from '@/store/session';
|
|
8
|
-
import { isFunctionMessage } from '@/utils/message';
|
|
9
|
-
|
|
10
|
-
import FunctionMessage from './FunctionMessage';
|
|
11
|
-
import MessageExtra from './MessageExtra';
|
|
12
|
-
|
|
13
|
-
const List = () => {
|
|
14
|
-
const { t } = useTranslation('common');
|
|
15
|
-
const data = useSessionStore(chatSelectors.currentChats, isEqual);
|
|
16
|
-
const [displayMode, deleteMessage, resendMessage, dispatchMessage] = useSessionStore(
|
|
17
|
-
(s) => [
|
|
18
|
-
agentSelectors.currentAgentConfigSafe(s).displayMode,
|
|
19
|
-
s.deleteMessage,
|
|
20
|
-
s.resendMessage,
|
|
21
|
-
s.dispatchMessage,
|
|
22
|
-
],
|
|
23
|
-
shallow,
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
const renderMessage = (content: ReactNode, message: ChatMessage) => {
|
|
27
|
-
if (message.role === 'function')
|
|
28
|
-
return isFunctionMessage(message.content) ? <FunctionMessage /> : content;
|
|
29
|
-
|
|
30
|
-
return content;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<ChatList
|
|
35
|
-
data={data}
|
|
36
|
-
onActionClick={(key, id) => {
|
|
37
|
-
switch (key) {
|
|
38
|
-
case 'delete': {
|
|
39
|
-
deleteMessage(id);
|
|
40
|
-
break;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
case 'regenerate': {
|
|
44
|
-
resendMessage(id);
|
|
45
|
-
break;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}}
|
|
49
|
-
onMessageChange={(id, content) => {
|
|
50
|
-
dispatchMessage({ id, key: 'content', type: 'updateMessage', value: content });
|
|
51
|
-
}}
|
|
52
|
-
renderMessage={renderMessage}
|
|
53
|
-
renderMessageExtra={MessageExtra}
|
|
54
|
-
style={{ marginTop: 24 }}
|
|
55
|
-
text={{
|
|
56
|
-
cancel: t('cancel'),
|
|
57
|
-
confirm: t('ok'),
|
|
58
|
-
copy: t('copy'),
|
|
59
|
-
copySuccess: t('copySuccess'),
|
|
60
|
-
delete: t('delete'),
|
|
61
|
-
edit: t('edit'),
|
|
62
|
-
regenerate: t('regenerate'),
|
|
63
|
-
}}
|
|
64
|
-
type={displayMode}
|
|
65
|
-
/>
|
|
66
|
-
);
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
export default memo(List);
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { LoadingOutlined } from '@ant-design/icons';
|
|
2
|
-
import { createStyles } from 'antd-style';
|
|
3
|
-
import { memo } from 'react';
|
|
4
|
-
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import { Flexbox } from 'react-layout-kit';
|
|
6
|
-
|
|
7
|
-
const useStyles = createStyles(({ css, token }) => ({
|
|
8
|
-
container: css`
|
|
9
|
-
padding: 4px 8px;
|
|
10
|
-
|
|
11
|
-
color: ${token.colorTextSecondary};
|
|
12
|
-
|
|
13
|
-
background: ${token.colorFillTertiary};
|
|
14
|
-
border: 1px solid ${token.colorBorder};
|
|
15
|
-
border-radius: 6px;
|
|
16
|
-
`,
|
|
17
|
-
}));
|
|
18
|
-
const FunctionMessage = memo(() => {
|
|
19
|
-
const { t } = useTranslation('plugin');
|
|
20
|
-
const { styles } = useStyles();
|
|
21
|
-
return (
|
|
22
|
-
<Flexbox className={styles.container} gap={8} horizontal>
|
|
23
|
-
<div>
|
|
24
|
-
<LoadingOutlined />
|
|
25
|
-
</div>
|
|
26
|
-
{t('pluginLoading')}
|
|
27
|
-
</Flexbox>
|
|
28
|
-
);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
export default FunctionMessage;
|