@adminforth/agent 1.34.2 → 1.36.0
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/agent/simpleAgent.ts +5 -0
- package/agent/tools/getUserLocation.ts +45 -0
- package/agent/tools/index.ts +2 -0
- package/build.log +9 -2
- package/custom/ChatSurface.vue +15 -0
- package/custom/composables/agentStore/constants.ts +12 -0
- package/custom/composables/agentStore/pageContext.ts +8 -0
- package/custom/composables/agentStore/useAgentChat.ts +69 -0
- package/custom/composables/agentStore/useAgentPlaceholder.ts +142 -0
- package/custom/composables/agentStore/useAgentSessions.ts +270 -0
- package/custom/composables/useAgentStore.ts +73 -393
- package/custom/conversation_area/ProcessingTimeline.vue +1 -1
- package/custom/env.d.ts +7 -0
- package/dist/agent/simpleAgent.js +3 -1
- package/dist/agent/tools/getUserLocation.js +31 -0
- package/dist/agent/tools/index.js +2 -0
- package/dist/custom/ChatSurface.vue +15 -0
- package/dist/custom/composables/agentStore/constants.ts +12 -0
- package/dist/custom/composables/agentStore/pageContext.ts +8 -0
- package/dist/custom/composables/agentStore/useAgentChat.ts +69 -0
- package/dist/custom/composables/agentStore/useAgentPlaceholder.ts +142 -0
- package/dist/custom/composables/agentStore/useAgentSessions.ts +270 -0
- package/dist/custom/composables/useAgentStore.ts +73 -393
- package/dist/custom/conversation_area/ProcessingTimeline.vue +1 -1
- package/dist/custom/env.d.ts +7 -0
- package/dist/index.js +264 -105
- package/index.ts +295 -103
- package/package.json +2 -2
- package/types.ts +6 -0
|
@@ -1,37 +1,22 @@
|
|
|
1
1
|
import { defineStore } from 'pinia';
|
|
2
|
-
import { IAgentSession, ISessionsListItem
|
|
3
|
-
import { ref, nextTick, computed, watch, onMounted
|
|
4
|
-
import { callAdminForthApi } from '@/utils';
|
|
2
|
+
import { IAgentSession, ISessionsListItem } from '../types';
|
|
3
|
+
import { ref, nextTick, computed, watch, onMounted } from 'vue';
|
|
5
4
|
import { useAdminforth } from '@/adminforth';
|
|
6
|
-
import { Chat } from '../chat';
|
|
7
|
-
import { DefaultChatTransport } from 'ai';
|
|
8
5
|
import { useCoreStore } from '@/stores/core';
|
|
9
6
|
import { useAgentTransitions } from './useAgentTransitions';
|
|
10
7
|
import { useWindowSize } from '@vueuse/core';
|
|
11
8
|
import { remToPx, pxToRem } from '../utils';
|
|
12
|
-
|
|
13
|
-
type AgentMode
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
title: document.title,
|
|
22
|
-
url: window.location.href,
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const DEFAULT_TEXTAREA_PLACEHOLDER = 'Type a message...';
|
|
27
|
-
const PLACEHOLDER_TYPING_DELAY_MS = 60;
|
|
28
|
-
const PLACEHOLDER_DELETING_DELAY_MS = 35;
|
|
29
|
-
const PLACEHOLDER_HOLD_DELAY_MS = 3000;
|
|
9
|
+
import {
|
|
10
|
+
type AgentMode,
|
|
11
|
+
DEFAULT_CHAT_WIDTH,
|
|
12
|
+
MAX_WIDTH,
|
|
13
|
+
MIN_WIDTH,
|
|
14
|
+
} from './agentStore/constants';
|
|
15
|
+
import { createAgentChatManager } from './agentStore/useAgentChat';
|
|
16
|
+
import { createAgentPlaceholderController } from './agentStore/useAgentPlaceholder';
|
|
17
|
+
import { createAgentSessionManager } from './agentStore/useAgentSessions';
|
|
30
18
|
|
|
31
19
|
export const useAgentStore = defineStore('agent', () => {
|
|
32
|
-
const DEFAULT_CHAT_WIDTH = 30;
|
|
33
|
-
const MAX_WIDTH = 60;
|
|
34
|
-
const MIN_WIDTH = 25
|
|
35
20
|
const agentTransitions = useAgentTransitions();
|
|
36
21
|
|
|
37
22
|
const activeSessionId = ref<string | null>(null);
|
|
@@ -43,8 +28,6 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
43
28
|
const isSessionHistoryOpen = ref(false);
|
|
44
29
|
const textInput = ref<HTMLTextAreaElement | null>(null);
|
|
45
30
|
const userMessageInput = ref();
|
|
46
|
-
const userMessagePlaceholder = ref(DEFAULT_TEXTAREA_PLACEHOLDER);
|
|
47
|
-
const placeholderMessages = ref<string[]>([]);
|
|
48
31
|
const trimmedUserMessage = computed(() => userMessageInput.value ? userMessageInput.value.trim() : '');
|
|
49
32
|
const lastMessage = ref('');
|
|
50
33
|
const isTeleportedToBody = ref(false);
|
|
@@ -58,13 +41,24 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
58
41
|
const chatWidth = ref(DEFAULT_CHAT_WIDTH);
|
|
59
42
|
const availableModes = ref<AgentMode[]>([]);
|
|
60
43
|
const activeModeName = ref<string | null>(null);
|
|
61
|
-
const hasTypedMessageInPageSession = ref(false);
|
|
62
44
|
const { width: windowWidth } = useWindowSize();
|
|
63
45
|
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
46
|
+
const {
|
|
47
|
+
currentChat,
|
|
48
|
+
setCurrentChat,
|
|
49
|
+
abortCurrentChatRequest,
|
|
50
|
+
} = createAgentChatManager({
|
|
51
|
+
lastMessage,
|
|
52
|
+
activeModeName,
|
|
53
|
+
});
|
|
54
|
+
const {
|
|
55
|
+
userMessagePlaceholder,
|
|
56
|
+
hasTypedMessageInPageSession,
|
|
57
|
+
fetchPlaceholderMessages,
|
|
58
|
+
stopPlaceholderAnimation,
|
|
59
|
+
} = createAgentPlaceholderController({
|
|
60
|
+
userMessageInput,
|
|
61
|
+
});
|
|
68
62
|
|
|
69
63
|
function setLocalStorageItem(key: string, value: string) {
|
|
70
64
|
window.localStorage.setItem(`${coreStore.config.brandName || 'adminforth'}-${key}`, value);
|
|
@@ -72,7 +66,35 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
72
66
|
function getLocalStorageItem(key: string) {
|
|
73
67
|
return window.localStorage.getItem(`${coreStore.config.brandName || 'adminforth'}-${key}`);
|
|
74
68
|
}
|
|
75
|
-
|
|
69
|
+
|
|
70
|
+
const isResponseInProgress = computed( () => {
|
|
71
|
+
return currentChat.value?.status === 'streaming';
|
|
72
|
+
});
|
|
73
|
+
const blockCloseOfChat = ref(false);
|
|
74
|
+
const {
|
|
75
|
+
sendMessage,
|
|
76
|
+
createPreSession,
|
|
77
|
+
setActiveSession,
|
|
78
|
+
fetchSessionsList,
|
|
79
|
+
deleteSession,
|
|
80
|
+
addDebugMessage,
|
|
81
|
+
addSystemMessage,
|
|
82
|
+
} = createAgentSessionManager({
|
|
83
|
+
activeSessionId,
|
|
84
|
+
currentSession,
|
|
85
|
+
sessionList,
|
|
86
|
+
sessions,
|
|
87
|
+
currentChat,
|
|
88
|
+
trimmedUserMessage,
|
|
89
|
+
isResponseInProgress,
|
|
90
|
+
userMessageInput,
|
|
91
|
+
lastMessage,
|
|
92
|
+
blockCloseOfChat,
|
|
93
|
+
adminforth,
|
|
94
|
+
setCurrentChat,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
watch(() => windowWidth.value, (newWidth) => {
|
|
76
98
|
if (isFullScreen.value) {
|
|
77
99
|
setChatWidth(newWidth, false);
|
|
78
100
|
}
|
|
@@ -94,16 +116,6 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
94
116
|
setLocalStorageItem('lastSessionId', newVal);
|
|
95
117
|
}
|
|
96
118
|
})
|
|
97
|
-
watch(userMessageInput, (newVal: unknown) => {
|
|
98
|
-
if (hasTypedMessageInPageSession.value) {
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (typeof newVal === 'string' && newVal.trim() !== '') {
|
|
103
|
-
hasTypedMessageInPageSession.value = true;
|
|
104
|
-
stopPlaceholderAnimation();
|
|
105
|
-
}
|
|
106
|
-
})
|
|
107
119
|
onMounted(() => {
|
|
108
120
|
const chatWidthBeforeFullScreen = parseInt(getLocalStorageItem('chatWidthBeforeFullScreen') || '0', 10);
|
|
109
121
|
if (chatWidthBeforeFullScreen && (chatWidthBeforeFullScreen > MAX_WIDTH || chatWidthBeforeFullScreen < MIN_WIDTH)) {
|
|
@@ -122,10 +134,11 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
122
134
|
}
|
|
123
135
|
if (!coreStore.isMobile) {
|
|
124
136
|
const savedIsTeleportedToBody = getLocalStorageItem('isTeleportedToBody');
|
|
137
|
+
const savedIsTeleportedToBodyBeforeFullScreen = getLocalStorageItem('isTeleportedToBodyBeforeFullScreen');
|
|
138
|
+
const isTeleportedToBodyFromLocalStorage = savedIsTeleportedToBody === 'true' || savedIsTeleportedToBodyBeforeFullScreen === 'true';
|
|
125
139
|
const savedIsChatOpen = getLocalStorageItem('isChatOpen');
|
|
126
|
-
const shouldTeleportToBody = savedIsTeleportedToBody === null ? true : savedIsTeleportedToBody === 'true';
|
|
127
140
|
|
|
128
|
-
setIsTeleportedToBody(
|
|
141
|
+
setIsTeleportedToBody(isTeleportedToBodyFromLocalStorage);
|
|
129
142
|
if (isTeleportedToBody.value) {
|
|
130
143
|
isChatOpen.value = savedIsChatOpen === null ? true : savedIsChatOpen === 'true';
|
|
131
144
|
}
|
|
@@ -137,10 +150,6 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
137
150
|
if (coreStore.isMobile) {
|
|
138
151
|
setChatWidth(window.innerWidth);
|
|
139
152
|
}
|
|
140
|
-
const ativeModeNameFromLocalStorage = getLocalStorageItem('activeModeName');
|
|
141
|
-
if (ativeModeNameFromLocalStorage) {
|
|
142
|
-
setActiveMode(ativeModeNameFromLocalStorage);
|
|
143
|
-
}
|
|
144
153
|
appRoot.value = document.getElementById('app');
|
|
145
154
|
header.value = document.getElementById('af-header-nav');
|
|
146
155
|
if (appRoot.value && header.value) {
|
|
@@ -207,6 +216,13 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
207
216
|
?? null;
|
|
208
217
|
}
|
|
209
218
|
|
|
219
|
+
function setCurrentGenerationModeFromLocalStorage() {
|
|
220
|
+
const activeModeNameFromLocalStorage = getLocalStorageItem('activeModeName');
|
|
221
|
+
if (activeModeNameFromLocalStorage) {
|
|
222
|
+
setActiveMode(activeModeNameFromLocalStorage);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
210
226
|
function setActiveMode(modeName: string) {
|
|
211
227
|
if (!availableModes.value.some((mode: AgentMode) => mode.name === modeName)) {
|
|
212
228
|
return;
|
|
@@ -215,138 +231,6 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
215
231
|
activeModeName.value = modeName;
|
|
216
232
|
}
|
|
217
233
|
|
|
218
|
-
function setCurrentChat(sessionId: string) {
|
|
219
|
-
if (chats.has(sessionId)) {
|
|
220
|
-
currentChat.value = chats.get(sessionId) || null;
|
|
221
|
-
} else {
|
|
222
|
-
const newChat = new Chat({
|
|
223
|
-
transport: new DefaultChatTransport({
|
|
224
|
-
api: `${import.meta.env.VITE_ADMINFORTH_PUBLIC_PATH || ''}/adminapi/v1/agent/response`,
|
|
225
|
-
credentials: 'include',
|
|
226
|
-
prepareSendMessagesRequest({ messages }: any) {
|
|
227
|
-
const message = lastMessage.value;
|
|
228
|
-
const body = {
|
|
229
|
-
message,
|
|
230
|
-
sessionId,
|
|
231
|
-
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
232
|
-
mode: activeModeName.value,
|
|
233
|
-
currentPage: getCurrentPageContext(),
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
return {
|
|
237
|
-
headers: {
|
|
238
|
-
Accept: 'text/event-stream',
|
|
239
|
-
'x-vercel-ai-ui-message-stream': 'v1',
|
|
240
|
-
},
|
|
241
|
-
body
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
}),
|
|
245
|
-
onError(error: unknown) {
|
|
246
|
-
console.error("Chat error:", error);
|
|
247
|
-
},
|
|
248
|
-
});
|
|
249
|
-
chats.set(sessionId, newChat);
|
|
250
|
-
currentChat.value = newChat;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
function clearPlaceholderAnimationTimer() {
|
|
256
|
-
if (placeholderAnimationTimer !== null) {
|
|
257
|
-
clearTimeout(placeholderAnimationTimer);
|
|
258
|
-
placeholderAnimationTimer = null;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
function resetPlaceholder() {
|
|
263
|
-
clearPlaceholderAnimationTimer();
|
|
264
|
-
userMessagePlaceholder.value = DEFAULT_TEXTAREA_PLACEHOLDER;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
function stopPlaceholderAnimation() {
|
|
268
|
-
resetPlaceholder();
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
function startPlaceholderAnimation(messages: string[]) {
|
|
272
|
-
clearPlaceholderAnimationTimer();
|
|
273
|
-
|
|
274
|
-
if (!messages.length) {
|
|
275
|
-
userMessagePlaceholder.value = DEFAULT_TEXTAREA_PLACEHOLDER;
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
let messageIndex = 0;
|
|
280
|
-
let visibleLength = 0;
|
|
281
|
-
let isDeleting = false;
|
|
282
|
-
|
|
283
|
-
const animate = () => {
|
|
284
|
-
const currentMessage = messages[messageIndex];
|
|
285
|
-
|
|
286
|
-
if (!currentMessage) {
|
|
287
|
-
resetPlaceholder();
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
if (!isDeleting) {
|
|
292
|
-
visibleLength += 1;
|
|
293
|
-
userMessagePlaceholder.value = currentMessage.slice(0, visibleLength);
|
|
294
|
-
|
|
295
|
-
if (visibleLength >= currentMessage.length) {
|
|
296
|
-
isDeleting = true;
|
|
297
|
-
placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_HOLD_DELAY_MS);
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_TYPING_DELAY_MS);
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
visibleLength -= 1;
|
|
306
|
-
userMessagePlaceholder.value = currentMessage.slice(0, Math.max(visibleLength, 0));
|
|
307
|
-
|
|
308
|
-
if (visibleLength <= 0) {
|
|
309
|
-
isDeleting = false;
|
|
310
|
-
messageIndex = (messageIndex + 1) % messages.length;
|
|
311
|
-
placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_TYPING_DELAY_MS);
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
placeholderAnimationTimer = setTimeout(animate, PLACEHOLDER_DELETING_DELAY_MS);
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
animate();
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
const isResponseInProgress = computed( () => {
|
|
322
|
-
return currentChat.value?.status === 'streaming';
|
|
323
|
-
});
|
|
324
|
-
const blockCloseOfChat = ref(false);
|
|
325
|
-
|
|
326
|
-
function sortSessionsListByTimestamp(sessionsList: ISessionsListItem[]) {
|
|
327
|
-
return [...sessionsList].sort((a: ISessionsListItem, b: ISessionsListItem) => b.timestamp.localeCompare(a.timestamp));
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
async function sendMessage() {
|
|
331
|
-
const message = trimmedUserMessage.value;
|
|
332
|
-
if (!message || isResponseInProgress.value) {
|
|
333
|
-
return;
|
|
334
|
-
}
|
|
335
|
-
if (!currentSession.value || currentSession.value.sessionId === 'pre-session') {
|
|
336
|
-
await createNewSession(message);
|
|
337
|
-
}
|
|
338
|
-
currentSession.value!.timestamp = new Date().toISOString();
|
|
339
|
-
sessionList.value = sortSessionsListByTimestamp(sessionList.value.map((s: ISessionsListItem) => s.sessionId === currentSession.value?.sessionId ? {
|
|
340
|
-
...s,
|
|
341
|
-
timestamp: currentSession.value?.timestamp || s.timestamp,
|
|
342
|
-
} : s));
|
|
343
|
-
lastMessage.value = message;
|
|
344
|
-
currentChat.value?.sendMessage({
|
|
345
|
-
text: message,
|
|
346
|
-
});
|
|
347
|
-
userMessageInput.value = '';
|
|
348
|
-
}
|
|
349
|
-
|
|
350
234
|
function closeChat() {
|
|
351
235
|
if(isFullScreen.value) {
|
|
352
236
|
document.body.style.overflow = '';
|
|
@@ -387,216 +271,9 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
387
271
|
textInput.value = el;
|
|
388
272
|
}
|
|
389
273
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
try {
|
|
397
|
-
const res = await callAdminForthApi({
|
|
398
|
-
method: 'POST',
|
|
399
|
-
path: '/agent/get-placeholder-messages',
|
|
400
|
-
});
|
|
401
|
-
|
|
402
|
-
if (res.error) {
|
|
403
|
-
console.error('Error fetching placeholder messages:', res.error);
|
|
404
|
-
placeholderMessages.value = [];
|
|
405
|
-
resetPlaceholder();
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
placeholderMessages.value = Array.isArray(res.messages)
|
|
410
|
-
? res.messages.filter((message: unknown): message is string => typeof message === 'string' && message.length > 0)
|
|
411
|
-
: [];
|
|
412
|
-
|
|
413
|
-
if (!placeholderMessages.value.length) {
|
|
414
|
-
resetPlaceholder();
|
|
415
|
-
return;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
startPlaceholderAnimation(placeholderMessages.value);
|
|
419
|
-
} catch (error) {
|
|
420
|
-
console.error('Error fetching placeholder messages', error);
|
|
421
|
-
placeholderMessages.value = [];
|
|
422
|
-
resetPlaceholder();
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
//create a pre-session, until user will type something, so we can save session
|
|
428
|
-
async function createPreSession() {
|
|
429
|
-
saveCurrentSessionInCache();
|
|
430
|
-
if (!sessionList.value.some((s: ISessionsListItem) => s.sessionId === 'pre-session')) {
|
|
431
|
-
sessionList.value.unshift({
|
|
432
|
-
sessionId: 'pre-session',
|
|
433
|
-
title: 'New Session',
|
|
434
|
-
timestamp: new Date().toISOString(),
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
activeSessionId.value = 'pre-session';
|
|
439
|
-
currentSession.value = {
|
|
440
|
-
sessionId: 'pre-session',
|
|
441
|
-
title: 'New Session',
|
|
442
|
-
timestamp: new Date().toISOString(),
|
|
443
|
-
messages: [],
|
|
444
|
-
};
|
|
445
|
-
sessions.value['pre-session'] = currentSession.value;
|
|
446
|
-
setCurrentChat('pre-session');
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
async function deletePreSession() {
|
|
450
|
-
sessionList.value = sessionList.value.filter((s: ISessionsListItem) => s.sessionId !== 'pre-session');
|
|
451
|
-
if (activeSessionId.value === 'pre-session') {
|
|
452
|
-
activeSessionId.value = null;
|
|
453
|
-
currentSession.value = null;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
async function createNewSession(triggerMessage?: string) {
|
|
458
|
-
try {
|
|
459
|
-
const res = await callAdminForthApi({
|
|
460
|
-
method: 'POST',
|
|
461
|
-
path: '/agent/create-session',
|
|
462
|
-
body: {
|
|
463
|
-
triggerMessage
|
|
464
|
-
},
|
|
465
|
-
});
|
|
466
|
-
if (res.error) {
|
|
467
|
-
console.error('Error creating new session:', res.error);
|
|
468
|
-
return;
|
|
469
|
-
}
|
|
470
|
-
deletePreSession();
|
|
471
|
-
sessions.value[res.sessionId] = res;
|
|
472
|
-
sessionList.value.unshift({
|
|
473
|
-
sessionId: res.sessionId,
|
|
474
|
-
title: res.title,
|
|
475
|
-
timestamp: new Date().toISOString(),
|
|
476
|
-
});
|
|
477
|
-
setActiveSession(res.sessionId);
|
|
478
|
-
} catch (error) {
|
|
479
|
-
console.error('Error creating new session', error);
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
async function deleteSession(sessionId: string) {
|
|
484
|
-
if (sessionId === 'pre-session') {
|
|
485
|
-
deletePreSession();
|
|
486
|
-
return;
|
|
487
|
-
}
|
|
488
|
-
blockCloseOfChat.value = true;
|
|
489
|
-
const isConfirmed = await adminforth.confirm({message: 'Are you sure, that you want to delete this session?', yes: 'Yes', no: 'No'})
|
|
490
|
-
blockCloseOfChat.value = false;
|
|
491
|
-
if (!isConfirmed) {
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
try {
|
|
495
|
-
const res = await callAdminForthApi({
|
|
496
|
-
method: 'POST',
|
|
497
|
-
path: '/agent/delete-session',
|
|
498
|
-
body: { sessionId },
|
|
499
|
-
});
|
|
500
|
-
if (res.error) {
|
|
501
|
-
console.error('Error deleting session:', res.error);
|
|
502
|
-
return;
|
|
503
|
-
}
|
|
504
|
-
delete sessions.value[sessionId];
|
|
505
|
-
sessionList.value = sessionList.value.filter((s: ISessionsListItem) => s.sessionId !== sessionId);
|
|
506
|
-
if (activeSessionId.value === sessionId) {
|
|
507
|
-
activeSessionId.value = null;
|
|
508
|
-
currentSession.value = null;
|
|
509
|
-
}
|
|
510
|
-
} catch (error) {
|
|
511
|
-
console.error('Error deleting session', error);
|
|
512
|
-
}
|
|
513
|
-
if(sessionId === activeSessionId.value) {
|
|
514
|
-
activeSessionId.value = sessionList.value.length > 0 ? sessionList.value[0].sessionId : null;
|
|
515
|
-
if (activeSessionId.value) {
|
|
516
|
-
currentSession.value = sessions.value[activeSessionId.value] || null;
|
|
517
|
-
} else {
|
|
518
|
-
currentSession.value = null;
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
async function fetchSession(sessionId: string) {
|
|
524
|
-
try {
|
|
525
|
-
const res = await callAdminForthApi({
|
|
526
|
-
method: 'POST',
|
|
527
|
-
path: '/agent/get-session-info',
|
|
528
|
-
body: { sessionId },
|
|
529
|
-
});
|
|
530
|
-
if (res.error) {
|
|
531
|
-
console.error('Error fetching session:', res.error);
|
|
532
|
-
return;
|
|
533
|
-
}
|
|
534
|
-
sessions.value[sessionId] = res.session;
|
|
535
|
-
setCurrentChat(sessionId);
|
|
536
|
-
} catch (error) {
|
|
537
|
-
console.error('Error fetching session', error);
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
function saveCurrentSessionInCache() {
|
|
542
|
-
if (currentSession.value) {
|
|
543
|
-
currentSession.value.messages = currentChat.value?.messages.map((m: any) => ({
|
|
544
|
-
role: m.role,
|
|
545
|
-
text: m.parts.map((p: IPart) => p.type === 'text' ? p.text : '').join(''),
|
|
546
|
-
})) || [];
|
|
547
|
-
sessions.value[currentSession.value.sessionId] = currentSession.value;
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
async function setActiveSession(sessionId: string) {
|
|
552
|
-
activeSessionId.value = sessionId;
|
|
553
|
-
saveCurrentSessionInCache();
|
|
554
|
-
if (!sessions.value[sessionId]) {
|
|
555
|
-
await fetchSession(sessionId);
|
|
556
|
-
}
|
|
557
|
-
currentSession.value = sessions.value[sessionId];
|
|
558
|
-
setCurrentChat(sessionId);
|
|
559
|
-
if (currentChat.value.messages.length === 0) {
|
|
560
|
-
currentChat.value.messages = currentSession.value?.messages.map((m: any) => ({
|
|
561
|
-
role: m.role,
|
|
562
|
-
parts:[{
|
|
563
|
-
type: 'text',
|
|
564
|
-
text: m.text,
|
|
565
|
-
state: 'done',
|
|
566
|
-
}]
|
|
567
|
-
}));
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
async function fetchSessionsList() {
|
|
572
|
-
try {
|
|
573
|
-
const res = await callAdminForthApi({
|
|
574
|
-
method: 'POST',
|
|
575
|
-
path: '/agent/get-sessions',
|
|
576
|
-
body: {
|
|
577
|
-
limit: 100,
|
|
578
|
-
},
|
|
579
|
-
});
|
|
580
|
-
if (res.error) {
|
|
581
|
-
console.error('Error fetching sessions list:', res.error);
|
|
582
|
-
return;
|
|
583
|
-
}
|
|
584
|
-
sessionList.value = res.sessions;
|
|
585
|
-
} catch (error) {
|
|
586
|
-
console.error('Error fetching sessions list', error);
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
function addDebugMessage(message: string) {
|
|
591
|
-
const debugMessage = {
|
|
592
|
-
role: 'assistant',
|
|
593
|
-
parts: [{
|
|
594
|
-
type: 'text',
|
|
595
|
-
text: message,
|
|
596
|
-
state: 'done',
|
|
597
|
-
}]
|
|
598
|
-
};
|
|
599
|
-
currentChat.value?.messages.push(debugMessage);
|
|
274
|
+
function abortCurrentChatRequestAndAddSystemMessage() {
|
|
275
|
+
abortCurrentChatRequest();
|
|
276
|
+
addSystemMessage('[Response generation aborted]');
|
|
600
277
|
}
|
|
601
278
|
|
|
602
279
|
return {
|
|
@@ -633,11 +310,14 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
633
310
|
availableModes,
|
|
634
311
|
activeModeName,
|
|
635
312
|
setAvailableModes,
|
|
313
|
+
setCurrentGenerationModeFromLocalStorage,
|
|
636
314
|
setActiveMode,
|
|
637
315
|
DEFAULT_CHAT_WIDTH,
|
|
638
316
|
MAX_WIDTH,
|
|
639
317
|
MIN_WIDTH,
|
|
640
318
|
getLocalStorageItem,
|
|
641
|
-
addDebugMessage
|
|
319
|
+
addDebugMessage,
|
|
320
|
+
abortCurrentChatRequestAndAddSystemMessage,
|
|
321
|
+
addSystemMessage
|
|
642
322
|
}
|
|
643
323
|
})
|
package/custom/env.d.ts
ADDED
|
@@ -19,6 +19,7 @@ export const contextSchema = z.object({
|
|
|
19
19
|
userTimeZone: z.string(),
|
|
20
20
|
sessionId: z.string(),
|
|
21
21
|
turnId: z.string(),
|
|
22
|
+
currentPage: z.custom().optional(),
|
|
22
23
|
httpExtra: z.custom().optional(),
|
|
23
24
|
emitToolCallEvent: z.custom(),
|
|
24
25
|
});
|
|
@@ -131,7 +132,7 @@ export function createAgentChatModel(params) {
|
|
|
131
132
|
}
|
|
132
133
|
export function callAgent(params) {
|
|
133
134
|
return __awaiter(this, void 0, void 0, function* () {
|
|
134
|
-
const { name, model, summaryModel, modelMiddleware = [], checkpointer, messages, adminUser, adminforth, apiBasedTools, customComponentsDir, sessionId, turnId, httpExtra, userTimeZone, emitToolCallEvent, sequenceDebugSink, } = params;
|
|
135
|
+
const { name, model, summaryModel, modelMiddleware = [], checkpointer, messages, adminUser, adminforth, apiBasedTools, customComponentsDir, sessionId, turnId, currentPage, httpExtra, userTimeZone, emitToolCallEvent, sequenceDebugSink, } = params;
|
|
135
136
|
const tools = yield createAgentTools(customComponentsDir, apiBasedTools);
|
|
136
137
|
const apiBasedToolsMiddleware = createApiBasedToolsMiddleware(apiBasedTools, adminforth);
|
|
137
138
|
const sequenceDebugMiddleware = createSequenceDebugMiddleware(sequenceDebugSink);
|
|
@@ -165,6 +166,7 @@ export function callAgent(params) {
|
|
|
165
166
|
userTimeZone,
|
|
166
167
|
sessionId,
|
|
167
168
|
turnId,
|
|
169
|
+
currentPage,
|
|
168
170
|
httpExtra,
|
|
169
171
|
emitToolCallEvent,
|
|
170
172
|
},
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { tool } from "langchain";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
const getUserLocationSchema = z.object({});
|
|
13
|
+
export function createGetUserLocationTool() {
|
|
14
|
+
return tool((_input, runtime) => __awaiter(this, void 0, void 0, function* () {
|
|
15
|
+
const currentPage = runtime.context.currentPage;
|
|
16
|
+
if (!currentPage) {
|
|
17
|
+
return JSON.stringify({
|
|
18
|
+
status: 404,
|
|
19
|
+
message: "Current user location is not available.",
|
|
20
|
+
}, null, 2);
|
|
21
|
+
}
|
|
22
|
+
return JSON.stringify({
|
|
23
|
+
status: 200,
|
|
24
|
+
location: currentPage,
|
|
25
|
+
}, null, 2);
|
|
26
|
+
}), {
|
|
27
|
+
name: "get_user_location",
|
|
28
|
+
description: "Get the user's current location in the AdminForth UI, including current page path, full path, title, and URL. Call this tool when you do not understand what the user is referring to, especially when they say here, this page, current page, opened page, or otherwise rely on page context.",
|
|
29
|
+
schema: getUserLocationSchema,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { createFetchSkillTool } from "./fetchSkill.js";
|
|
11
11
|
import { createFetchToolSchemaTool } from "./fetchToolSchema.js";
|
|
12
12
|
import { createApiTool } from "./apiTool.js";
|
|
13
|
+
import { createGetUserLocationTool } from "./getUserLocation.js";
|
|
13
14
|
export const ALWAYS_AVAILABLE_API_TOOL_NAMES = ["get_resource"];
|
|
14
15
|
export function createAgentTools(customComponentsDir, apiBasedTools) {
|
|
15
16
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -21,6 +22,7 @@ export function createAgentTools(customComponentsDir, apiBasedTools) {
|
|
|
21
22
|
}
|
|
22
23
|
return createApiTool(toolName, apiBasedTool);
|
|
23
24
|
}),
|
|
25
|
+
createGetUserLocationTool(),
|
|
24
26
|
yield createFetchSkillTool(customComponentsDir),
|
|
25
27
|
yield createFetchToolSchemaTool(apiBasedTools),
|
|
26
28
|
];
|
|
@@ -170,6 +170,7 @@
|
|
|
170
170
|
</div>
|
|
171
171
|
</div>
|
|
172
172
|
<Button
|
|
173
|
+
v-if="!agentStore.isResponseInProgress"
|
|
173
174
|
class="absolute right-4 bottom-2 !p-0 h-9 w-9"
|
|
174
175
|
@click="sendMessage"
|
|
175
176
|
:disabled="!agentStore.trimmedUserMessage || agentStore.isResponseInProgress"
|
|
@@ -179,6 +180,15 @@
|
|
|
179
180
|
text-white"
|
|
180
181
|
/>
|
|
181
182
|
</Button>
|
|
183
|
+
<Button
|
|
184
|
+
v-else
|
|
185
|
+
class="absolute right-4 bottom-2 !p-0 h-9 w-9"
|
|
186
|
+
@click="stopCurrentRequest"
|
|
187
|
+
>
|
|
188
|
+
<div
|
|
189
|
+
class="w-3 h-3 bg-white rounded-sm"
|
|
190
|
+
/>
|
|
191
|
+
</Button>
|
|
182
192
|
</div>
|
|
183
193
|
</div>
|
|
184
194
|
</div>
|
|
@@ -231,6 +241,7 @@ onClickOutside(modeMenu, () => { isModeMenuOpen.value = false; });
|
|
|
231
241
|
|
|
232
242
|
onMounted(async () => {
|
|
233
243
|
agentStore.setAvailableModes(props.meta.modes, props.meta.defaultModeName);
|
|
244
|
+
agentStore.setCurrentGenerationModeFromLocalStorage();
|
|
234
245
|
agentStore.regisrerTextInput(textInput.value);
|
|
235
246
|
window.addEventListener('resize', updateHeight)
|
|
236
247
|
textInput.value?.focus();
|
|
@@ -316,6 +327,10 @@ async function sendMessage() {
|
|
|
316
327
|
conversationArea.value?.handleSendMessage();
|
|
317
328
|
}
|
|
318
329
|
|
|
330
|
+
function stopCurrentRequest() {
|
|
331
|
+
agentStore.abortCurrentChatRequestAndAddSystemMessage();
|
|
332
|
+
}
|
|
333
|
+
|
|
319
334
|
function updateHeight() {
|
|
320
335
|
dvh.value = Math.round(window.visualViewport?.height || window.innerHeight);
|
|
321
336
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type AgentMode = {
|
|
2
|
+
name: string;
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
export const DEFAULT_CHAT_WIDTH = 30;
|
|
6
|
+
export const MAX_WIDTH = 60;
|
|
7
|
+
export const MIN_WIDTH = 25;
|
|
8
|
+
|
|
9
|
+
export const DEFAULT_TEXTAREA_PLACEHOLDER = 'Type a message...';
|
|
10
|
+
export const PLACEHOLDER_TYPING_DELAY_MS = 60;
|
|
11
|
+
export const PLACEHOLDER_DELETING_DELAY_MS = 35;
|
|
12
|
+
export const PLACEHOLDER_HOLD_DELAY_MS = 3000;
|