@blueking/ai-ui-sdk 0.0.14 → 0.0.15-beta.2

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.
Files changed (55) hide show
  1. package/dist/common/chart-helper.d.ts +1 -1
  2. package/dist/common/chart-helper.js +173 -0
  3. package/dist/common/util.d.ts +21 -0
  4. package/dist/common/util.js +143 -0
  5. package/dist/css/fonts/iconcool.eot +0 -0
  6. package/dist/css/fonts/iconcool.svg +53 -0
  7. package/dist/css/fonts/iconcool.ttf +0 -0
  8. package/dist/css/fonts/iconcool.woff +0 -0
  9. package/dist/css/iconcool.js +10 -0
  10. package/dist/css/style.css +43 -0
  11. package/dist/event/index.d.ts +4 -0
  12. package/dist/event/index.js +17 -0
  13. package/dist/hooks/use-chat.d.ts +843 -18
  14. package/dist/hooks/use-chat.js +533 -0
  15. package/dist/hooks/use-click-proxy.js +77 -0
  16. package/dist/hooks/use-http.d.ts +15 -0
  17. package/dist/hooks/use-http.js +48 -0
  18. package/dist/hooks/use-reference-doc.d.ts +1 -1
  19. package/dist/hooks/use-reference-doc.js +185 -0
  20. package/dist/hooks/use-style.js +11 -0
  21. package/dist/hooks/use-summary.d.ts +1 -1
  22. package/dist/hooks/use-summary.js +55 -0
  23. package/dist/hooks/use-think.js +135 -0
  24. package/dist/http/fetch/error-interceptor.d.ts +3 -0
  25. package/dist/http/fetch/error-interceptor.js +7 -0
  26. package/dist/http/fetch/index.d.ts +25 -0
  27. package/dist/http/fetch/index.js +182 -0
  28. package/dist/http/fetch/request-error.d.ts +6 -0
  29. package/dist/http/fetch/request-error.js +25 -0
  30. package/dist/http/fetch/success-interceptor.d.ts +3 -0
  31. package/dist/http/fetch/success-interceptor.js +92 -0
  32. package/dist/http/helper/knowledge.d.ts +43 -0
  33. package/dist/http/helper/knowledge.js +227 -0
  34. package/dist/http/helper/permission.d.ts +7 -0
  35. package/dist/http/helper/permission.js +28 -0
  36. package/dist/http/helper/session.d.ts +31 -0
  37. package/dist/http/helper/session.js +147 -0
  38. package/dist/http/helper/tool.d.ts +13 -0
  39. package/dist/http/helper/tool.js +49 -0
  40. package/dist/main.d.ts +13 -2
  41. package/dist/main.js +24 -239
  42. package/dist/types/enum.d.ts +39 -0
  43. package/dist/types/enum.js +105 -0
  44. package/dist/types/file.d.ts +13 -0
  45. package/dist/types/file.js +1 -0
  46. package/dist/types/knowledge.d.ts +133 -0
  47. package/dist/types/knowledge.js +1 -0
  48. package/dist/types/permission.d.ts +48 -0
  49. package/dist/types/permission.js +1 -0
  50. package/dist/types/{type.d.ts → session.d.ts} +84 -23
  51. package/dist/types/session.js +1 -0
  52. package/dist/types/tool.d.ts +60 -0
  53. package/dist/types/tool.js +1 -0
  54. package/package.json +3 -3
  55. package/dist/common/type-transform.d.ts +0 -7
@@ -0,0 +1,533 @@
1
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
2
+ try {
3
+ var info = gen[key](arg);
4
+ var value = info.value;
5
+ } catch (error) {
6
+ reject(error);
7
+ return;
8
+ }
9
+ if (info.done) {
10
+ resolve(value);
11
+ } else {
12
+ Promise.resolve(value).then(_next, _throw);
13
+ }
14
+ }
15
+ function _async_to_generator(fn) {
16
+ return function() {
17
+ var self = this, args = arguments;
18
+ return new Promise(function(resolve, reject) {
19
+ var gen = fn.apply(self, args);
20
+ function _next(value) {
21
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
22
+ }
23
+ function _throw(err) {
24
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
25
+ }
26
+ _next(undefined);
27
+ });
28
+ };
29
+ }
30
+ import { ref, computed } from 'vue';
31
+ import { HttpErrorCode, SessionContentRole, SessionContentStatus } from '../types/enum.js';
32
+ import { getHtmlContentFromDocuments, removeReferenceDoc } from './use-reference-doc.js';
33
+ import { getHtmlContentFromThink, isThinking, removeThink } from './use-think.js';
34
+ import { useHttp } from './use-http.js';
35
+ import { transferSessionContent2SessionPrompt } from '../http/helper/session.js';
36
+ import { ChatHelper } from '../common/chart-helper.js';
37
+ import { processPromptTemplate, throttle } from '../common/util.js';
38
+ // ai 聊天
39
+ export const useChat = ({ handleStart, handleText, handleReferenceDoc, handleThink, handleEnd, handleError, requestOptions })=>{
40
+ // 接口
41
+ const { clearSession: clearSessionApi, getSessions: getSessionsApi, plusSession: plusSessionApi, modifySession: modifySessionApi, deleteSession: deleteSessionApi, batchDeleteSessions: batchDeleteSessionsApi, getSession: getSessionApi, getSessionContents: getSessionContentsApi, plusSessionContent: plusSessionContentApi, modifySessionContent: modifySessionContentApi, deleteSessionContent: deleteSessionContentApi, batchDeleteSessionContents: batchDeleteSessionContentsApi } = useHttp(requestOptions.url);
42
+ const startMessage = '内容正在生成中...';
43
+ // 聊天上下文
44
+ const currentSession = ref();
45
+ const sessionLoadingMap = ref({});
46
+ const sessionContents = ref([]);
47
+ const sessionContentsMap = {};
48
+ // 通过计算得到的会话列表
49
+ const calculatedSessionContents = computed(()=>{
50
+ const calculatedSessionContents = [];
51
+ for(let index = sessionContents.value.length - 1; index >= 0; index--){
52
+ const sessionContent = sessionContents.value[index];
53
+ // 向下找到下一个ai回复
54
+ let nextAiSessionContentIndex = index + 1;
55
+ let nextAiSessionContent = sessionContents.value[nextAiSessionContentIndex];
56
+ while(nextAiSessionContent && ![
57
+ SessionContentRole.Ai,
58
+ SessionContentRole.TokenExpired,
59
+ SessionContentRole.ImageNotSupported,
60
+ SessionContentRole.Pause,
61
+ SessionContentRole.Guide
62
+ ].includes(nextAiSessionContent.role)){
63
+ nextAiSessionContentIndex += 1;
64
+ nextAiSessionContent = sessionContents.value[nextAiSessionContentIndex];
65
+ }
66
+ // 系统消息,退出
67
+ if (sessionContent.role === SessionContentRole.System) {
68
+ break;
69
+ }
70
+ // 倒叙添加当前聊天上下文 排除异常答复、异常问题 & 系统消息和时间消息
71
+ if (sessionContent.status !== SessionContentStatus.Fail && !((nextAiSessionContent === null || nextAiSessionContent === void 0 ? void 0 : nextAiSessionContent.status) === SessionContentStatus.Fail && [
72
+ SessionContentRole.User,
73
+ SessionContentRole.UserImage
74
+ ].includes(sessionContent.role)) && ![
75
+ SessionContentRole.Time,
76
+ SessionContentRole.System
77
+ ].includes(sessionContent.role)) {
78
+ calculatedSessionContents.unshift(sessionContent);
79
+ }
80
+ }
81
+ return calculatedSessionContents;
82
+ });
83
+ // 当前会话是否正在加载
84
+ const currentSessionLoading = computed(()=>{
85
+ var _currentSession_value;
86
+ const sessionCode = (_currentSession_value = currentSession.value) === null || _currentSession_value === void 0 ? void 0 : _currentSession_value.sessionCode;
87
+ return sessionCode ? sessionLoadingMap.value[sessionCode] : false;
88
+ });
89
+ // 计算当前的 prompt
90
+ const prompts = computed(()=>{
91
+ var _currentSession_value_roleInfo_content, _currentSession_value_roleInfo, _currentSession_value;
92
+ const rolePrompts = [];
93
+ const userPrompts = [];
94
+ const prompts = [];
95
+ // build rolePrompts
96
+ const latestMatchIndex = sessionContents.value.findLastIndex((sessionContent)=>sessionContent.role === SessionContentRole.System && [
97
+ '已启用角色',
98
+ '已启用模型'
99
+ ].some((key)=>sessionContent.content.includes(key)));
100
+ let index = 0;
101
+ (_currentSession_value = currentSession.value) === null || _currentSession_value === void 0 ? void 0 : (_currentSession_value_roleInfo = _currentSession_value.roleInfo) === null || _currentSession_value_roleInfo === void 0 ? void 0 : (_currentSession_value_roleInfo_content = _currentSession_value_roleInfo.content) === null || _currentSession_value_roleInfo_content === void 0 ? void 0 : _currentSession_value_roleInfo_content.forEach((roleContent)=>{
102
+ const sessionContent = sessionContents.value[latestMatchIndex + 1 + index];
103
+ let nextSessionContent = sessionContents.value[latestMatchIndex + 2 + index];
104
+ if ((sessionContent === null || sessionContent === void 0 ? void 0 : sessionContent.content) === roleContent.content && sessionContent.role !== SessionContentRole.System) {
105
+ rolePrompts.push(transferSessionContent2SessionPrompt(sessionContent));
106
+ index += 1;
107
+ if ((sessionContent === null || sessionContent === void 0 ? void 0 : sessionContent.role) === SessionContentRole.Pause) {
108
+ while(nextSessionContent && nextSessionContent.role === SessionContentRole.System){
109
+ index += 1;
110
+ nextSessionContent = sessionContents.value[latestMatchIndex + 1 + index];
111
+ }
112
+ while(nextSessionContent && [
113
+ SessionContentRole.User,
114
+ SessionContentRole.UserImage
115
+ ].includes(nextSessionContent.role)){
116
+ rolePrompts.push(transferSessionContent2SessionPrompt(nextSessionContent));
117
+ index += 1;
118
+ nextSessionContent = sessionContents.value[latestMatchIndex + 1 + index];
119
+ }
120
+ }
121
+ }
122
+ });
123
+ // build userPrompts
124
+ userPrompts.push(...calculatedSessionContents.value.map(transferSessionContent2SessionPrompt));
125
+ const isSameContent = (startIndex)=>{
126
+ let isSame = true;
127
+ for(let index = startIndex; index < rolePrompts.length; index++){
128
+ var _userPrompts_;
129
+ const rolePrompt = rolePrompts[index];
130
+ if (rolePrompt.content !== ((_userPrompts_ = userPrompts[index - startIndex]) === null || _userPrompts_ === void 0 ? void 0 : _userPrompts_.content)) {
131
+ isSame = false;
132
+ }
133
+ }
134
+ return isSame;
135
+ };
136
+ // 排除在一个系统消息里面,重复的情况
137
+ for(let index = 0; index < rolePrompts.length; index++){
138
+ const rolePrompt = rolePrompts[index];
139
+ if (isSameContent(index)) {
140
+ break;
141
+ } else {
142
+ prompts.push(rolePrompt);
143
+ }
144
+ }
145
+ prompts.push(...userPrompts);
146
+ // 删除引用资料
147
+ prompts.forEach((prompt)=>{
148
+ prompt.content = removeThink(prompt.content);
149
+ prompt.content = removeReferenceDoc(prompt.content);
150
+ });
151
+ return prompts;
152
+ });
153
+ const chatHelper = new ChatHelper({
154
+ handleStart: handleStartChat,
155
+ handleText: handleTextChat,
156
+ handleReferenceDoc: handleReferenceDocChat,
157
+ handleThink: handleThinkChat,
158
+ handleEnd: handleEndChat,
159
+ handleError: handleErrorChat
160
+ });
161
+ // 新增 db
162
+ function plusSessionContent2Db(sessionContent) {
163
+ return plusSessionContentApi(sessionContent).then((result)=>{
164
+ sessionContent.id = result.id;
165
+ sessionContent.createdAt = result.createdAt;
166
+ return sessionContent;
167
+ });
168
+ }
169
+ // 防抖更新 db
170
+ const throttleModifySessionContentApi = throttle((id, sessionContent)=>modifySessionContentApi(sessionContent), 1000);
171
+ // 设置 currentSession
172
+ function setCurrentSession(session) {
173
+ currentSession.value = session;
174
+ // 空session,不处理
175
+ if (!(session === null || session === void 0 ? void 0 : session.sessionCode)) return;
176
+ if (!sessionContentsMap[session.sessionCode]) {
177
+ sessionContentsMap[session.sessionCode] = [];
178
+ }
179
+ sessionContents.value = sessionContentsMap[session.sessionCode];
180
+ }
181
+ // 设置 sessionContents
182
+ function setSessionContents(data) {
183
+ if (!currentSession.value) return;
184
+ sessionContentsMap[currentSession.value.sessionCode] = data;
185
+ sessionContents.value = data;
186
+ }
187
+ // 获取 SessionContent 通过 id
188
+ function getSessionContentById(id, sessionCode) {
189
+ const sessionContents = getSessionContentsBySessionCode(sessionCode);
190
+ return sessionContents.find((item)=>item.id === id);
191
+ }
192
+ // 获取执行中的 SessionContent(最后一个)
193
+ function getLastSessionContentBySessionCode(sessionCode) {
194
+ var _currentSession_value;
195
+ if (((_currentSession_value = currentSession.value) === null || _currentSession_value === void 0 ? void 0 : _currentSession_value.sessionCode) === sessionCode) {
196
+ return sessionContents.value.at(-1);
197
+ }
198
+ return sessionContentsMap[sessionCode].at(-1);
199
+ }
200
+ // 获取 SessionContents
201
+ function getSessionContentsBySessionCode(sessionCode) {
202
+ var _currentSession_value;
203
+ if (((_currentSession_value = currentSession.value) === null || _currentSession_value === void 0 ? void 0 : _currentSession_value.sessionCode) === sessionCode) {
204
+ return sessionContents.value;
205
+ }
206
+ return sessionContentsMap[sessionCode];
207
+ }
208
+ // 新增 sessionContent
209
+ function plusSessionContent(sessionCode, sessionContent) {
210
+ const sessionContents = getSessionContentsBySessionCode(sessionCode);
211
+ sessionContents.push(sessionContent);
212
+ return plusSessionContent2Db(sessionContent);
213
+ }
214
+ // 更新 chatContent
215
+ function updateSessionContent(sessionContent) {
216
+ var _currentSession_value;
217
+ const currentSessionContents = ((_currentSession_value = currentSession.value) === null || _currentSession_value === void 0 ? void 0 : _currentSession_value.sessionCode) === sessionContent.sessionCode ? sessionContents.value : sessionContentsMap[sessionContent.sessionCode];
218
+ const currentSessionContent = currentSessionContents.find((item)=>+(item.id || 0) === +(sessionContent.id || 0));
219
+ if (currentSessionContent) {
220
+ Object.assign(currentSessionContent, sessionContent);
221
+ }
222
+ return throttleModifySessionContentApi(sessionContent.id, sessionContent);
223
+ }
224
+ // 获取待删除的会话id,并从会话列表中删除
225
+ function getDeleteSessionContents(sessionCode, sessionContentIds, relatedDelete) {
226
+ var _currentSession_value;
227
+ const currentSessionContents = ((_currentSession_value = currentSession.value) === null || _currentSession_value === void 0 ? void 0 : _currentSession_value.sessionCode) === sessionCode ? sessionContents.value : sessionContentsMap[sessionCode];
228
+ const deleteSessionContentIds = [];
229
+ sessionContentIds.forEach((sessionContentId)=>{
230
+ const index = currentSessionContents.findIndex((sessionContent)=>sessionContent.id === sessionContentId);
231
+ if (index > -1) {
232
+ const preSessionContent = currentSessionContents[index - 1];
233
+ const nextSessionContent = currentSessionContents[index + 1];
234
+ const nextNextSessionContent = currentSessionContents[index + 2];
235
+ // 删除当前会话
236
+ currentSessionContents.splice(index, 1);
237
+ deleteSessionContentIds.push(sessionContentId);
238
+ // 如果前一个是 hidden 也需要删除
239
+ if ([
240
+ SessionContentRole.Hidden
241
+ ].includes(preSessionContent === null || preSessionContent === void 0 ? void 0 : preSessionContent.role)) {
242
+ const hiddenIndex = currentSessionContents.findIndex((sessionContent)=>sessionContent.id === preSessionContent.id);
243
+ currentSessionContents.splice(hiddenIndex, 1);
244
+ deleteSessionContentIds.push(preSessionContent.id);
245
+ }
246
+ // 如果下一个是ai回复,也需要删掉
247
+ if ((nextSessionContent === null || nextSessionContent === void 0 ? void 0 : nextSessionContent.role) === SessionContentRole.Ai || relatedDelete && [
248
+ SessionContentRole.Ai,
249
+ SessionContentRole.Guide,
250
+ SessionContentRole.TokenExpired,
251
+ SessionContentRole.ImageNotSupported,
252
+ SessionContentRole.Pause
253
+ ].includes(nextSessionContent === null || nextSessionContent === void 0 ? void 0 : nextSessionContent.role)) {
254
+ const nextIndex = currentSessionContents.findIndex((sessionContent)=>sessionContent.id === nextSessionContent.id);
255
+ currentSessionContents.splice(nextIndex, 1);
256
+ deleteSessionContentIds.push(nextSessionContent.id);
257
+ }
258
+ // 如果下下个是 guide,需要删除
259
+ if ([
260
+ SessionContentRole.Guide
261
+ ].includes(nextNextSessionContent === null || nextNextSessionContent === void 0 ? void 0 : nextNextSessionContent.role) && relatedDelete) {
262
+ const nextNextIndex = currentSessionContents.findIndex((sessionContent)=>sessionContent.id === nextNextSessionContent.id);
263
+ currentSessionContents.splice(nextNextIndex, 1);
264
+ deleteSessionContentIds.push(nextNextSessionContent.id);
265
+ }
266
+ }
267
+ });
268
+ return deleteSessionContentIds;
269
+ }
270
+ // 删除聊天内容
271
+ function deleteSessionContent(sessionCode, contentId) {
272
+ const deleteSessionContentIds = getDeleteSessionContents(sessionCode, [
273
+ contentId
274
+ ], true);
275
+ return batchDeleteSessionContentsApi(deleteSessionContentIds);
276
+ }
277
+ // 批量删除
278
+ function deleteSessionContents(sessionCode, contentIds) {
279
+ const deleteSessionContentIds = getDeleteSessionContents(sessionCode, contentIds, false);
280
+ return batchDeleteSessionContentsApi(deleteSessionContentIds);
281
+ }
282
+ function handleStartChat(sessionCode) {
283
+ return _handleStartChat.apply(this, arguments);
284
+ }
285
+ function _handleStartChat() {
286
+ _handleStartChat = // 聊天开始
287
+ _async_to_generator(function*(sessionCode) {
288
+ sessionLoadingMap.value[sessionCode] = true;
289
+ const sessionContent = {
290
+ sessionCode,
291
+ role: SessionContentRole.Ai,
292
+ status: SessionContentStatus.Loading,
293
+ content: startMessage
294
+ };
295
+ // 画布新增
296
+ yield plusSessionContent(sessionCode, sessionContent);
297
+ // 调用cb
298
+ return handleStart === null || handleStart === void 0 ? void 0 : handleStart(sessionCode, sessionContent);
299
+ });
300
+ return _handleStartChat.apply(this, arguments);
301
+ }
302
+ function handleReferenceDocChat(sessionCode, documents, cover) {
303
+ return _handleReferenceDocChat.apply(this, arguments);
304
+ }
305
+ function _handleReferenceDocChat() {
306
+ _handleReferenceDocChat = // 引用资料
307
+ _async_to_generator(function*(sessionCode, documents, cover) {
308
+ const sessionContent = getLastSessionContentBySessionCode(sessionCode);
309
+ const content = getHtmlContentFromDocuments(documents);
310
+ sessionContent.content = cover ? content : sessionContent.content + content;
311
+ yield throttleModifySessionContentApi(sessionContent.id, sessionContent);
312
+ return handleReferenceDoc === null || handleReferenceDoc === void 0 ? void 0 : handleReferenceDoc(sessionCode, sessionContent);
313
+ });
314
+ return _handleReferenceDocChat.apply(this, arguments);
315
+ }
316
+ function handleThinkChat(sessionCode, content, cover, elapsedTime) {
317
+ return _handleThinkChat.apply(this, arguments);
318
+ }
319
+ function _handleThinkChat() {
320
+ _handleThinkChat = // 思考
321
+ _async_to_generator(function*(sessionCode, content, cover, elapsedTime) {
322
+ const sessionContent = getLastSessionContentBySessionCode(sessionCode);
323
+ // 获取思考的html
324
+ sessionContent.content = getHtmlContentFromThink(sessionContent.content, content, cover, elapsedTime);
325
+ // 更新 db
326
+ yield throttleModifySessionContentApi(sessionContent.id, sessionContent);
327
+ // 调用cb
328
+ return handleThink === null || handleThink === void 0 ? void 0 : handleThink(sessionCode, sessionContent);
329
+ });
330
+ return _handleThinkChat.apply(this, arguments);
331
+ }
332
+ function handleTextChat(sessionCode, message, cover) {
333
+ return _handleTextChat.apply(this, arguments);
334
+ }
335
+ function _handleTextChat() {
336
+ _handleTextChat = // 文本
337
+ _async_to_generator(function*(sessionCode, message, cover) {
338
+ const sessionContent = getLastSessionContentBySessionCode(sessionCode);
339
+ if (sessionContent.content === startMessage) {
340
+ sessionContent.content = message;
341
+ } else if (sessionContent.status === SessionContentStatus.Loading) {
342
+ sessionContent.content = cover ? message : sessionContent.content + message;
343
+ } else {
344
+ return;
345
+ }
346
+ // 更新 db
347
+ yield throttleModifySessionContentApi(sessionContent.id, sessionContent);
348
+ // 调用cb
349
+ return handleText === null || handleText === void 0 ? void 0 : handleText(sessionCode, sessionContent);
350
+ });
351
+ return _handleTextChat.apply(this, arguments);
352
+ }
353
+ function handleEndChat(sessionCode, message) {
354
+ return _handleEndChat.apply(this, arguments);
355
+ }
356
+ function _handleEndChat() {
357
+ _handleEndChat = // 聊天结束
358
+ _async_to_generator(function*(sessionCode, message) {
359
+ const sessionContent = getLastSessionContentBySessionCode(sessionCode);
360
+ // 内容正在生成中或者正在思考中
361
+ if (sessionContent.content === startMessage || isThinking(sessionContent.content)) {
362
+ handleErrorChat(sessionCode, '聊天内容已中断');
363
+ return;
364
+ }
365
+ // 防止 error 的情况下异步触发 end 更新了数据
366
+ if (sessionContent.status === SessionContentStatus.Loading) {
367
+ sessionLoadingMap.value[sessionCode] = false;
368
+ // end 的时候,如果 message 有值,则更新 content
369
+ if (message) {
370
+ sessionContent.content = message;
371
+ }
372
+ // 更新状态
373
+ sessionContent.status = SessionContentStatus.Success;
374
+ // 更新 db
375
+ yield throttleModifySessionContentApi(sessionContent.id, sessionContent);
376
+ // 调用cb
377
+ return handleEnd === null || handleEnd === void 0 ? void 0 : handleEnd(sessionCode, sessionContent);
378
+ }
379
+ });
380
+ return _handleEndChat.apply(this, arguments);
381
+ }
382
+ function handleErrorChat(sessionCode, message, code) {
383
+ return _handleErrorChat.apply(this, arguments);
384
+ }
385
+ function _handleErrorChat() {
386
+ _handleErrorChat = // 聊天异常
387
+ _async_to_generator(function*(sessionCode, message, code) {
388
+ const sessionContent = getLastSessionContentBySessionCode(sessionCode);
389
+ sessionContent.status = SessionContentStatus.Fail;
390
+ sessionContent.content = message;
391
+ sessionLoadingMap.value[sessionCode] = false;
392
+ // token 超了,提示 token 不足
393
+ if (code === HttpErrorCode.TokenExpired) {
394
+ sessionContent.content = '抱歉,您的剩余 Token 不足,无法返回回答内容,请先清空当前会话(上下文仍会作为历史记录保留))';
395
+ sessionContent.role = SessionContentRole.TokenExpired;
396
+ }
397
+ if (code === HttpErrorCode.ImageNotSupported) {
398
+ sessionContent.content = '抱歉,当前模型不支持图片内容解析';
399
+ sessionContent.role = SessionContentRole.ImageNotSupported;
400
+ }
401
+ // 更新 db
402
+ yield throttleModifySessionContentApi(sessionContent.id, sessionContent);
403
+ // 调用cb
404
+ return handleError === null || handleError === void 0 ? void 0 : handleError(sessionCode, sessionContent, code);
405
+ });
406
+ return _handleErrorChat.apply(this, arguments);
407
+ }
408
+ // 重新生成对话 仅支持重新生成 ai 的回复
409
+ function reGenerateChat(chatIndex) {
410
+ const chat = sessionContents.value[chatIndex];
411
+ if (chat.role !== SessionContentRole.Ai) {
412
+ return;
413
+ }
414
+ const message = sessionContents.value[chatIndex - 1].content;
415
+ const cite = sessionContents.value[chatIndex - 1].cite;
416
+ sessionContents.value.splice(chatIndex - 1, sessionContents.value.length - chatIndex + 1); // 重新生成时,删除当前的 ai 回复和下方的所有内容
417
+ sendChat({
418
+ message,
419
+ cite
420
+ });
421
+ }
422
+ // 聊天
423
+ function chat({ sessionCode, data, url, headers }) {
424
+ // 发送请求
425
+ chatHelper.stream({
426
+ sessionCode,
427
+ url: url,
428
+ data,
429
+ headers: headers || (requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.headers)
430
+ });
431
+ }
432
+ // 重新发送聊天, 需要将当前聊天内容以及下方的所有内容删除
433
+ function reSendChat(index, { message, cite }, callback) {
434
+ const chat = sessionContents.value[index];
435
+ if (chat.role !== SessionContentRole.User) {
436
+ return;
437
+ }
438
+ sessionContents.value.splice(index, sessionContents.value.length - index);
439
+ sendChat({
440
+ message,
441
+ cite
442
+ }, callback);
443
+ }
444
+ // 发送聊天
445
+ function sendChat(content, callback) {
446
+ var _currentSession_value, _currentSession_value1, _currentSession_value2;
447
+ if (!((_currentSession_value = currentSession.value) === null || _currentSession_value === void 0 ? void 0 : _currentSession_value.sessionCode) || !(requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.url) || currentSessionLoading.value) {
448
+ return;
449
+ }
450
+ const { message, cite, shortcut } = content;
451
+ let input = '';
452
+ if (shortcut) {
453
+ input = processPromptTemplate(shortcut.prompt, cite);
454
+ } else {
455
+ input = cite ? `${message}: "${cite}"` : message;
456
+ }
457
+ sessionContents.value.push({
458
+ sessionCode: (_currentSession_value1 = currentSession.value) === null || _currentSession_value1 === void 0 ? void 0 : _currentSession_value1.sessionCode,
459
+ content: message,
460
+ role: SessionContentRole.User,
461
+ status: SessionContentStatus.Success,
462
+ cite
463
+ });
464
+ // 发送请求
465
+ chatHelper.stream({
466
+ sessionCode: (_currentSession_value2 = currentSession.value) === null || _currentSession_value2 === void 0 ? void 0 : _currentSession_value2.sessionCode,
467
+ url: requestOptions.url,
468
+ headers: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.headers,
469
+ data: {
470
+ inputs: {
471
+ chat_history: prompts.value.slice(0, prompts.value.length - 1),
472
+ input
473
+ }
474
+ }
475
+ });
476
+ callback === null || callback === void 0 ? void 0 : callback();
477
+ }
478
+ /**
479
+ * 删除聊天内容
480
+ * @param index 要删除的聊天内容索引
481
+ * @description
482
+ * - 如果删除的是用户消息,则同时删除该消息及其对应的AI回复(共2条)
483
+ * - 如果删除的是其他类型消息(如AI回复),则只删除该条消息
484
+ */ function deleteChat(index) {
485
+ const chat = sessionContents.value[index];
486
+ if (chat.role === SessionContentRole.User) {
487
+ sessionContents.value.splice(index, 2);
488
+ return;
489
+ }
490
+ sessionContents.value.splice(index - 1, 2);
491
+ }
492
+ // 停止聊天
493
+ function stopChat(sessionCode) {
494
+ chatHelper.stop(sessionCode);
495
+ }
496
+ return {
497
+ currentSession,
498
+ sessionContents,
499
+ sessionContentsMap,
500
+ sessionLoadingMap,
501
+ prompts,
502
+ currentSessionLoading,
503
+ chat,
504
+ sendChat,
505
+ stopChat,
506
+ plusSessionContent,
507
+ updateSessionContent,
508
+ getSessionContentById,
509
+ getLastSessionContentBySessionCode,
510
+ getSessionContentsBySessionCode,
511
+ setCurrentSession,
512
+ setSessionContents,
513
+ deleteSessionContent,
514
+ deleteSessionContents,
515
+ handleStartChat,
516
+ handleErrorChat,
517
+ reGenerateChat,
518
+ reSendChat,
519
+ deleteChat,
520
+ clearSessionApi,
521
+ getSessionsApi,
522
+ plusSessionApi,
523
+ modifySessionApi,
524
+ deleteSessionApi,
525
+ batchDeleteSessionsApi,
526
+ getSessionApi,
527
+ getSessionContentsApi,
528
+ plusSessionContentApi,
529
+ modifySessionContentApi,
530
+ deleteSessionContentApi,
531
+ batchDeleteSessionContentsApi
532
+ };
533
+ };
@@ -0,0 +1,77 @@
1
+ import { onBeforeMount, onBeforeUnmount } from 'vue';
2
+ import { handleCopy, handleDownLoad, getFullScreenWrap } from '../common/util.js';
3
+ // 全局点击代理事件
4
+ export const useClickProxy = ()=>{
5
+ const clickProxy = (e)=>{
6
+ const target = e.target;
7
+ // 聊天窗里面的引用资料和思考内容
8
+ if (target === null || target === void 0 ? void 0 : target.classList.contains('bkaidev-angle-up')) {
9
+ const parent = target === null || target === void 0 ? void 0 : target.parentElement;
10
+ if (parent === null || parent === void 0 ? void 0 : parent.classList.contains('closed')) {
11
+ parent === null || parent === void 0 ? void 0 : parent.classList.remove('closed');
12
+ } else {
13
+ parent === null || parent === void 0 ? void 0 : parent.classList.add('closed');
14
+ }
15
+ }
16
+ if (target === null || target === void 0 ? void 0 : target.classList.contains('click-close')) {
17
+ if (target === null || target === void 0 ? void 0 : target.classList.contains('closed')) {
18
+ target === null || target === void 0 ? void 0 : target.classList.remove('closed');
19
+ } else {
20
+ target === null || target === void 0 ? void 0 : target.classList.add('closed');
21
+ }
22
+ }
23
+ // 会话里面代码块的全屏
24
+ if (target === null || target === void 0 ? void 0 : target.classList.contains('click-full-screen')) {
25
+ // 获取全屏的父元素
26
+ const fullScreenWrap = getFullScreenWrap(target);
27
+ // 添加 class
28
+ fullScreenWrap === null || fullScreenWrap === void 0 ? void 0 : fullScreenWrap.classList.add('full-screen');
29
+ // 元素移动到body
30
+ if (!fullScreenWrap._originalParent) {
31
+ fullScreenWrap._originalParent = fullScreenWrap.parentNode;
32
+ fullScreenWrap._originalNextSibling = fullScreenWrap.nextSibling;
33
+ }
34
+ document.body.appendChild(fullScreenWrap);
35
+ }
36
+ // 会话里面代码块的取消全屏
37
+ if (target === null || target === void 0 ? void 0 : target.classList.contains('click-un-full-screen')) {
38
+ // 获取全屏的父元素
39
+ const fullScreenWrap = getFullScreenWrap(target);
40
+ // 移除 class
41
+ fullScreenWrap === null || fullScreenWrap === void 0 ? void 0 : fullScreenWrap.classList.remove('full-screen');
42
+ // 移回原位
43
+ if (fullScreenWrap._originalNextSibling) {
44
+ fullScreenWrap._originalParent.insertBefore(fullScreenWrap, fullScreenWrap._originalNextSibling);
45
+ } else {
46
+ fullScreenWrap._originalParent.appendChild(fullScreenWrap);
47
+ }
48
+ }
49
+ // 复制
50
+ if (target === null || target === void 0 ? void 0 : target.classList.contains('click-copy')) {
51
+ const text = target === null || target === void 0 ? void 0 : target.getAttribute('data-clipboard-text');
52
+ if (text) {
53
+ handleCopy(decodeURIComponent(text));
54
+ }
55
+ }
56
+ // 下载
57
+ if (target === null || target === void 0 ? void 0 : target.classList.contains('click-download')) {
58
+ const text = target === null || target === void 0 ? void 0 : target.getAttribute('data-clipboard-text');
59
+ const fileName = target === null || target === void 0 ? void 0 : target.getAttribute('data-file-name');
60
+ if (text && fileName) {
61
+ handleDownLoad(decodeURIComponent(text), fileName);
62
+ }
63
+ }
64
+ };
65
+ const addClickProxy = ()=>{
66
+ window.addEventListener('click', clickProxy);
67
+ };
68
+ const removeClickProxy = ()=>{
69
+ window.removeEventListener('click', clickProxy);
70
+ };
71
+ onBeforeMount(()=>{
72
+ addClickProxy();
73
+ });
74
+ onBeforeUnmount(()=>{
75
+ removeClickProxy();
76
+ });
77
+ };
@@ -0,0 +1,15 @@
1
+ import type { ISession, ISessionContent } from '@/types/session';
2
+ export declare const useHttp: (apiPrefix: string) => {
3
+ clearSession: (sessionCode: string) => Promise<unknown>;
4
+ getSessions: () => Promise<ISession[]>;
5
+ plusSession: (data: ISession) => Promise<ISession>;
6
+ modifySession: (data: ISession) => Promise<ISession>;
7
+ deleteSession: (sessionCode: string) => Promise<unknown>;
8
+ batchDeleteSessions: (sessionCodes: string[]) => Promise<number>;
9
+ getSession: (sessionCode: string) => Promise<ISession>;
10
+ getSessionContents: (sessionCode: string) => Promise<ISessionContent[]>;
11
+ plusSessionContent: (data: ISessionContent) => Promise<ISessionContent>;
12
+ modifySessionContent: (data: ISessionContent) => Promise<ISessionContent>;
13
+ deleteSessionContent: (id: number) => Promise<ISessionContent>;
14
+ batchDeleteSessionContents: (ids: number[]) => Promise<number>;
15
+ };
@@ -0,0 +1,48 @@
1
+ import fetch from '../http/fetch/index.js';
2
+ import { transferSession2SessionApi, transferSessionApi2Session, transferSessionContent2SessionContentApi, transferSessionContentApi2SessionContent } from '../http/helper/session.js';
3
+ export const useHttp = (apiPrefix)=>{
4
+ // 清除聊天上下文
5
+ const clearSession = (sessionCode)=>fetch.post(`${apiPrefix}/chat_completion/${sessionCode}/clear/`);
6
+ // 获取会话列表
7
+ const getSessions = ()=>fetch.get(`${apiPrefix}/session/`).then((res)=>res.map(transferSessionApi2Session));
8
+ // 新增会话
9
+ const plusSession = (data)=>fetch.post(`${apiPrefix}/session/`, transferSession2SessionApi(data)).then((res)=>transferSessionApi2Session(res));
10
+ // 修改会话
11
+ const modifySession = (data)=>fetch.put(`${apiPrefix}/session/${data.sessionCode}/`, transferSession2SessionApi(data)).then((res)=>transferSessionApi2Session(res));
12
+ // 删除会话
13
+ const deleteSession = (sessionCode)=>fetch.delete(`${apiPrefix}/session/${sessionCode}/`);
14
+ // 批量删除会话
15
+ const batchDeleteSessions = (sessionCodes)=>fetch.post(`${apiPrefix}/session/batch_delete/`, {
16
+ session_codes: sessionCodes
17
+ });
18
+ // 获取会话资源
19
+ const getSession = (sessionCode)=>fetch.get(`${apiPrefix}/session/${sessionCode}/`).then((res)=>transferSessionApi2Session(res));
20
+ // 获取会话内容列表
21
+ const getSessionContents = (sessionCode)=>fetch.get(`${apiPrefix}/session_content/content/`, {
22
+ session_code: sessionCode
23
+ }).then((res)=>res.map(transferSessionContentApi2SessionContent));
24
+ // 新增会话内容
25
+ const plusSessionContent = (data)=>fetch.post(`${apiPrefix}/session_content/`, transferSessionContent2SessionContentApi(data));
26
+ // 修改会话内容
27
+ const modifySessionContent = (data)=>fetch.put(`${apiPrefix}/session_content/${data.id}/`, transferSessionContent2SessionContentApi(data));
28
+ // 删除会话内容
29
+ const deleteSessionContent = (id)=>fetch.delete(`${apiPrefix}/session_content/${id}/`);
30
+ // 批量删除聊天内容
31
+ const batchDeleteSessionContents = (ids)=>fetch.post(`${apiPrefix}/session_content/batch_delete/`, {
32
+ ids
33
+ });
34
+ return {
35
+ clearSession,
36
+ getSessions,
37
+ plusSession,
38
+ modifySession,
39
+ deleteSession,
40
+ batchDeleteSessions,
41
+ getSession,
42
+ getSessionContents,
43
+ plusSessionContent,
44
+ modifySessionContent,
45
+ deleteSessionContent,
46
+ batchDeleteSessionContents
47
+ };
48
+ };